Discussion:
"run as administrator" changes default directory
(too old to reply)
Matt Hickman
2007-07-24 04:50:42 UTC
Permalink
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?

Thanks

--
Mat Hickman
Andrew McLaren
2007-07-24 06:42:18 UTC
Permalink
Post by Matt Hickman
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,
--
Andrew McLaren
amclar (at) optusnet dot com dot au
Matt Hickman
2007-07-25 15:49:57 UTC
Permalink
On Jul 24, 1:42 am, "Andrew McLaren" <***@fakeaddress.com> wrote:

Thanks, your sample was very helpful. Although I did find that the "/
D" parameter works better for directory paths that contain spaces:

REM =========== top ===========
FOR /D %%I IN (%0) DO CD /d %%~dpI
REM ========= bottom ===========

Using quotes around "%0" caused me problems as well. (If you allow
the "FOR" command to echo, you wll see that "%0" is implemented with
quotes already)
This isn't really a bug inVista, 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.
I am not sure that is the case. Do a "set" at the command line after
you start cmd.exe selecting "Run as administrator", When I did, I
found I was in the context of my own ID:
...
USERNAME=Matt
USERPROFILE=F:\Users\Matt
...
Not quite like running a batch file in NT as a scheduled task using
AT.EXE (talk about having to be explicit...)
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".
I explicitly hope that MS developers pay more attention to down-level/
cross-level compatibility -- especially when there is no apparent
reason to change system behavior.

Again thanks for the help.

--
Matt Hickman
Matt -***@t- thehickmans -d.ot- US
Andrew McLaren
2007-07-25 23:04:11 UTC
Permalink
Post by Matt Hickman
Using quotes around "%0" caused me problems as well. (If you allow
the "FOR" command to echo, you wll see that "%0" is implemented with
quotes already)
Actually, the quote marks you see there are inserted by Explorer. When you
run the batch file from Explorer it internally puts quote marks around the
string, I guess to deal with path names containing spaces. If you run the
batch file from a command prompt, %0 is plain unadorned, wthout quotes.
Post by Matt Hickman
I am not sure that is the case. Do a "set" at the command line after
you start cmd.exe selecting "Run as administrator", When I did, I
...
USERNAME=Matt
USERPROFILE=F:\Users\Matt
Right. Actually, it gets more complicated :-) and I kind of glossed over the
complexity (didn't want to drown the post with superfluous information).

If your Administrator account is explicitly enabled (ie, the user with SID
S-1-5-21-2621085430-3789323321-3897899910-500) and you "Run as
Administrator" then you get the environment of the Administrator. In this
case you really do see:
USERNAME=administrator
USERPROFILE=C:\Users\administrator
etc

By default in Vista, the built-in Administrator account is disabled, and the
"user" you first create at setup is a member of the Administrator's group.
Except when you log in as this user, they don't get a full administrative
security token straight way - Vista uses the concept of the "split token".
When you elevate, either via Run As" or via an internal EXE manifest, then
you get a full administrative token for the particular operation you
elevated for. Exactly what bits of the user context remain the same and
which vary is, I will concede, a bit mixed up. You'll probably find, for
example, that any drives you had mapped as a "regular user" no longer work
in the elevated context; because drive mappings aren't carried across to the
elevated context (I shouldn't say "environment" because the "User
Enviroment" strings are only one partial aspect of the user's total
context).

Some detailed info (admittedly a bit mind-numbing) here:
http://msdn2.microsoft.com/en-us/library/bb530410.aspx
Post by Matt Hickman
I explicitly hope that MS developers pay more attention to down-level/
cross-level compatibility -- especially when there is no apparent
reason to change system behavior.
Well, there *was* a reason to change the behaviour - security. The behaviour
you're seeing is a side effect of improved security in Vista. Microsoft
certainly would not have bothered making these particular changes, unless
there was a good reason (granted, in Vista they did seem to dick around with
Explorer, Control Panel, etc, on a mere whim. But CMD is old, gnarly code,
which no-one touches if they can help it). The security benefits may not be
immediately obvious, but then, most of security is a subtle cat-n-mouse game
which moved beyond the obvious, comon-sense stage, sometime around 1996.

But wait! There's good news. CMD and batch files are bing superceded by
PowerShell:
http://www.microsoft.com/windowsserver2003/technologies/management/powershell/default.mspx.
PowerShell is an entirely new comand processor and scritping language,
designed from scratch. It is available for Vista and will be installed by
default in Windows Server 2008 and Windows 7. CMD will still be there for
legacy batch files; but PowerShell gives you vastly more control (in a
consistent, understandable, predicable, composible manner) than CMD.

Cheers,
--
Andrew McLaren
amclar (at) optusnet dot com dot au
cquirke (MVP Windows shell/user)
2007-07-26 13:58:29 UTC
Permalink
On Mon, 23 Jul 2007 21:50:42 -0700, Matt Hickman
Post by Matt Hickman
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?
I would try using NT's extended batch file syntax to derive the
location of the program file to define that as current, using the
relevant syntax. Does mean not DOS/Win9x-compatible, tho.

@Echo
Echo This program is %0
Echo It is running on drive %~d0
Echo It is running from directory %~p0
Echo We are currently here...
CD
Echo ...changing this location...
%~d0
CD %~dp0
Echo We are now here:
CD

You can do a huge amount with this un-pretty but powerful syntax.
Play with %~?0 where ? = x n s t z d p etc. or do the Help thing.
Post by Matt Hickman
--------------- ----- ---- --- -- - - -
To one who only has a hammer,
everything looks like a nail
Post by Matt Hickman
--------------- ----- ---- --- -- - - -
c***@gmail.com
2014-04-19 11:58:13 UTC
Permalink
A simple two-line solution here at my blog.

http://chienyiing.blogspot.com/2014/04/batch-file-run-as-administrator-changes.html


@setlocal enableextensions
@cd /d "%~dp0"

Loading...