Matt Hickman said:
I have a batch script, setup.cmd, which depends on the default
directory, when it runs, being the directory where the script is
located. So if setup.cmd is located in c:\temp, that batch file
should run with c:\temp as its default directory.
Under Vista, setup.cmd needs to be run using the "run as
administrator" option. However, when I run it this way, the default
directory is \windows\system32.
what is the work-around for this bug?
Hi Matt,
This isn't really a bug in Vista, as such; although it's probably a pretty
surprising "feature".
When you run the Batch file "as Administrator", you are running it in a
different user context than the interactive user. Details of the environment
like "current directory" are tied to the user context. When you run the
batch file "as administrator" it takes the environment settings of the
administrator, not of the logged in user. The administrator doesn't know (or
care) what the current directory of user "MattH" is, it just goes ahead and
runs the batch file with its own environment.
In programming terms - in the past, your coding effort has been made easier
by certain convenient assumptions, which however were not guarranteed to
always be there (ie current directory will be the location of the batch
file). So like any good programmer, you need to supply explicit values in
place of implicit assumptions, as "defensive programming".
Getting more practical ... the location of the batch file itself is stored
on the %0 parameter of the batch file's runtime environment. In Windows
2000, XP, 2003 and Vista, the so-called "Command Extensions" are enabled by
default. These give batch files many facilities which weren't available
under MS-DOS. Once of these is substitution performed by the FOR command.
Type "for /?" at a command prompt, for the full description of the syntax.
By running FOR over the %0 variable, you can extract the name of the
directory the batch file lives in, from %0; no matter what the current
directory is. Here's an example:
REM =========== top ===========
@ECHO OFF
ECHO The current directory is %CD%
PAUSE
ECHO The running batch file is %0
PAUSE
FOR /F %%I IN ("%0") DO SET BATDIR=%%~dpI
ECHO The batch file is located in directory %BATDIR%
ECHO.
CD /D %BATDIR%
CD
PAUSE
SET BATDIR=
:END
REM ========= bottom ===========
As described in the "FOR /?" help text:
The modifiers can be combined to get compound results:
%~dpI - expands %I to a drive letter and path only
So - the line "FOR /F %%I IN ("%0") DO SET BATDIR=%%~DPI" is setting a new
variable %BATDIR%, to a value which is the drive letter and path only, of
%0, the location of the batch file. Then we explicitly CD to %BATDIR%, and
the current directory will be the directory the batch file is located in.
It's easy!
There's a small curiosity about %0. If you echo %0 to the console, it will
display as the command used to launch the batch file. So if you supply the
full pathname on the command line, echo %0 will show the full pathname. If
the directory was on your PATH and you launched the file with just the file
name, no directory and no extension, it will echo just the filename. But
doing text substitution on %0 will always use the full drive and path name
to the file, including extension.
The rest is left as an exercise for the reader
Hope this helps,