Thursday, August 09, 2007

Getting a Batch File's Directory

Tonight I ran into a problem trying to uninstall a Windows Service via a batch file. The batch file is simple:

C:\Program Files\MyProduct\uninstsvc.cmd
@echo off
:: get the Framework directory
set NETFX=%SYSTEMROOT%\Microsoft.NET\Framework\v2.0.50727
:: stop the service
net stop MyService
:: uninstall the service
%NETFX%\installutil /u MyService.exe


Since MyService.exe is in the same directory as the batch file, this works as long as my working directory is C:\Program Files\MyProduct. However, if I call the batch file from any other working directory, I get this output:
Uninstalling MyService service...
Microsoft (R) .NET Framework Installation utility Version 2.0.50727.312
Copyright (c) Microsoft Corporation. All rights reserved.

Exception occurred while initializing the installation:
System.IO.FileNotFoundException: Could not load file or assembly 'file:///D:\Some\Other\Working\Directory\MyService.exe' or one of its dependencies. The system cannot find the file specified..


This could be easily solved by using the full path to MyService.exe in the batch file:
installutil /u C:\Program Files\MyProduct\MyService.exe
But what if my end user doesn't install my product in the default directory? I want the batch file to just look for MyService.exe in the same directory where the batch file itself is stored.

I knew that you can use variables like %1, %2, etc. to get the parameters passed into a batch file, and %0 to get the full name of the batch file itself -- but I didn't know that you could use modifiers on those variables to extract different pieces of the path.

In my service uninstaller, I need to get the path to the batch file, but exclude the batch file name. I can do that using %~dp0, which represents the drive and path portion of the file %0.
%0 = C:\Program Files\MyProduct\uninstsvc.cmd
%~d0 = C:
%~p0 = \Program Files\MyProduct\
%~dp0 = C:\Program Files\MyProduct\


There are several other useful modifiers too: Using Batch Parameters. This ended up saving me a lot of time because I didn't have to make the application installer modify the batch file dynamically to include the full installation path. Sometimes you just can't beat a decent batch file. :)

4 comments:

Anonymous said...

Thank you. You saved me some valuable time.

dvmurthy said...

Thanks a lot. This tip is a gem.

One thing I realized when I used it was that spaces in the path name will cause the batch file to fail unless you enclose the variable name in quotes as in

"%~dp0\filename.ext"

da9l said...

Thanks! This was the solution I was looking for!

Anonymous said...

As above, thanks.