I have to execute the ewfmgr.exe
which can be executed only when the Command window is opened as an Admin.
If I go to Start
->type cmd.exe
->Right click
->Run as Administrator
then the following Comand prompt windows appear. In this window, if I write ewfmgr.exe
(which the EXE file that I have to execute), then the command is executed without any problem.
image http://imageshack.com/a/img922/9500/k0subw.png
MY REQUIREMENT: My requirement is to execute the command through a script file (RunasAdmin.cmd
file) and this script file will be executed through an NSIS Installer.
Since, the ewfmgr.exe
can be executed only with Admin, so I have to escalate my script to get Admin rights. For this, I have the following script:
Script to Get Admin Right: "(RunasAdmin.cmd)"
::::::::::::::::::::::::::::::::::::::::::::
:: Elevate.cmd - Version 4
:: Automatically check & get admin rights
::::::::::::::::::::::::::::::::::::::::::::
@echo off
CLS
ECHO.
ECHO =============================
ECHO Running Admin shell
ECHO =============================
:init
setlocal DisableDelayedExpansion
set cmdInvoke=0
set winSysFolder=System32
set "batchPath=%~0"
for %%k in (%0) do set batchName=%%~nk
set "vbsGetPrivileges=%temp%\OEgetPriv_%batchName%.vbs"
setlocal EnableDelayedExpansion
:checkPrivileges
NET FILE 1>NUL 2>NUL
if '%errorlevel%' == '0' ( goto gotPrivileges ) else ( goto getPrivileges )
:getPrivileges
if '%1'=='ELEV' (echo ELEV & shift /1 & goto gotPrivileges)
ECHO.
ECHO **************************************
ECHO Invoking UAC for Privilege Escalation
ECHO **************************************
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%vbsGetPrivileges%"
ECHO args = "ELEV " >> "%vbsGetPrivileges%"
ECHO For Each strArg in WScript.Arguments >> "%vbsGetPrivileges%"
ECHO args = args ^& strArg ^& " " >> "%vbsGetPrivileges%"
ECHO Next >> "%vbsGetPrivileges%"
if '%cmdInvoke%'=='1' goto InvokeCmd
ECHO UAC.ShellExecute "!batchPath!", args, "", "runas", 1 >> "%vbsGetPrivileges%"
goto ExecElevation
:InvokeCmd
ECHO args = "/c """ + "!batchPath!" + """ " + args >> "%vbsGetPrivileges%"
ECHO UAC.ShellExecute "%SystemRoot%\%winSysFolder%\cmd.exe", args, "", "runas", 1 >> "%vbsGetPrivileges%"
:ExecElevation
"%SystemRoot%\%winSysFolder%\WScript.exe" "%vbsGetPrivileges%" %*
exit /B
:gotPrivileges
setlocal & pushd .
cd /d %~dp0
if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul & shift /1)
::::::::::::::::::::::::::::
::START
::::::::::::::::::::::::::::
REM Run shell as admin (example) - put here code as you like
ewfmgr c: -enable
pause
cmd /k
PROBLEM: If I execute the script (RunasAdmin.cmd
) just by double clicking on it, the script is executed and get the task done without any error. But if I execute the script (RunasAdmin.cmd
) through my NSIS installer (EWFMGR_Run.exe
) then, I get an error that ewfmgr is not recognised as an internal or external command
NSIS Installer Code: (EWFMGR_Run.exe)
OutFile "EWFMGR_Run.exe"
section
ExecWait "D:\Disk\RunasAdmin.cmd"
sectionEnd
The Command window opened by NSIS installer after running the script (RunasAdmin.cmd
) is following:
image http://imageshack.com/a/img924/8846/vZnI70.png
Queston: Both the command windows are opened as Admin and are into the same working directory. But how come the window opened by NSIS installer is not able to find ewfmgr.exe
?
UPDATE-1: Bascially the problem is in the CMD window opened by the NSIS installer. Even if I move to the path C:\Windows\System32
manually using cd /D C:\Windows\System32
and try to execute ewfmgr.exe
(which is available in that path), CMD does not recognize it.
References: The script file to elevate to Admin has been taken from Matt's answer given here.
Try modifying RunasAdmin.cmd to use Sysnative instead of System32:
set winSysFolder=Sysnative
I am guessing that EWFMGR_Run.exe is launching a 32 bit cmd window and windows is forcing the c:\windows\syswow64 override on your attempted override of set winSysFolder=System32
According to this article, you should be using the Sysnative virtual folder instead.
What must be at least taken into account on elevating a command script (batch file) to administrator level?
The current directory changes in any case to
%SystemRoot%\System32
.The environment could change completely if the current user is not in administrator group and therefore the user has to use a different user account to run the batch file with elevated privileges of an administrator, for example the local administrator account must be used instead of current user account. This affects environment variables and permissions on network resources.
The script is started initially always in environment of parent process which is on 64-bit Windows the 32-bit environment instead of the 64-bit environment in case of parent process is a 32-bit application.
The script could be executed with 1 or more arguments enclosed in double quotes which should be passed to the script on execution with elevated privileges right.
How to handle those 4 points?
1. Current directory
Many command line scripts (batch files) are coded to work with current directory and assume that the current directory is the same directory as the batch file. That the current directory is the same directory in which the batch file is stored is true on double clicking on a batch file stored on a local drive or a network drive, except the execution of batch files from network drives is disabled by security settings.
But Windows sets
%SystemRoot%\System32
as current directory on running a cmd script as scheduled task using system account.And Windows sets
%SystemRoot%\System32
as current directory on usingRunAs
to run a cmd script with elevated administrator privileges.And Windows sets
%SystemRoot%
as current directory after printing into console window the message below on executing a batch file with a double click which is stored on a network share opened using UNC path.Using UNC paths as current directory could be enabled as described for example by an answer on How to run batch file from network share without "UNC path are not supported" message?
The best would be to write the entire script code to work independent on which directory is the current directory.
That means not using just the file name of a referenced file, but
"Full path to\FileName.exe"
, i.e. the file name with file extension and with full path enclosed in double quotes.In case of all files to run or referenced from within a cmd script are stored in an unknown folder, but are always in same folder as the cmd script, the simple method to get path for all files is using the command line:
%~dp0
expands to path of the batch file always ending with a backslash and never being enclosed in double quotes even if the folder path contains a space character or other command line syntax critical characters like an ampersand.Then all files are referenced with using
Note: There is not backslash (directory separator on Windows) as the environment variable
SourceFolder
holds the folder path already with a backslash at end.Of course it is also possible to use
cd /D "%~dp0"
to set current directory to the directory of the cmd script, but this does not work for UNC paths.But there is also the command
pushd "%~dp0"
working also with UNC paths if command extensions are enabled as by default.For details on the commands CD and PUSHD run in a command prompt window
cd /?
andpushd /?
and read the output help.2. Environment variables
Windows creates a copy of the currently active environment table of current process whenever a new process is created.
But this is not the case when a batch file elevates itself to administrator level. Therefore it is not possible to define environment variables on initial run of a batch file, then elevate to administrator level, and access now the environment variables as defined before in initial environment. It could even happen that the batch file was initially executed in 32-bit environment on 64-bit Windows on initial execution, but runs in 64-bit environment after elevation to administrator level.
So everything which needs to be passed from initial execution to elevated execution must be parsed via command line arguments or via a file on a local drive fully accessible in all environments, i.e. for everyone.
3. 32-bit versus 64-bit environment
Sometimes a 32-bit installer is used for installing either a 32-bit or a 64-bit application depending on bit width of Windows because of running on all Windows. The batch file is processed by 32-bit
cmd.exe
in 32-bit environment on using a 32-bit installer even when executed on a 64-bit Windows.At least the following three Microsoft articles should be studied carefully before reading further:
It is definitely no good idea to depend on value of environment variable
PROCESSOR_ARCHITECTURE
as its value isx86
when a 32-bit process is executed on 64-bit Windows in 32-bit environment.It is also not good to query the architecture of the processor directly from Windows registry. It is not guaranteed that there is a 64-bit Windows running on a computer with a 64-bit CPU. It is not often done, but nevertheless possible to use 32-bit Windows on a computer with a 64-bit processor on main board.
The environment variable
ProgramFiles(x86)
is not defined by default on 32-bit Windows as it is on 64-bit Windows which can be used to determine if a command file script is running on 32-bit or 64-bit Windows.And the file
%SystemRoot%\Sysnative\cmd.exe
exists only for 32-bit processes running in 32-bit environment on 64-bit Windows because of special aliasSysnative
existing only for a 32-bit process in 32-bit environment on 64-bit Windows which can be used to determine in which environment the batch file is currently running.4. Passing arguments
It is easy to elevate a batch file executed without any arguments to elevated administrator level.
It is also no problem to pass simple arguments which do not need to be enclosed in double quotes to batch file running elevated.
But passing 1 or more arguments containing at least 1 space character or one of these characters
&()[]{}^=;!'+,`~<|>
which require enclosing the argument string in double quotes is really not easy, especially on creating a VBScript from within a batch file to elevate to administrator level.It is a real nightmare to try to encode double quotes in batch file correct to be passed via the VBScript to the same batch file executed with elevated privileges. Most solutions provided in world wide web simply don't support double quoted parameters. Matt's Elevate.cmd - Version 4 is no exception. Running a batch file using this code with
"%ProgramFiles%\Installation Folder"
as first argument results on initial execution in"C:\Program Files\Installation Folder"
being the first and only argument and on elevated execution after removing argumentELEV
in the 3 argumentsC:\Program
,Files\Installation
andFolder
.5. Possible solution for this task
For this task a 32-bit NSIS installer is calling a command line script which must elevate itself to administrator level and should run on 64-bit Windows in 64-bit environment instead of 32-bit environment as on initial run.
I have once analyzed the batch and VBscript code of Matt's Elevate.cmd - Version 4, have removed all useless code, have enhanced it to support also arguments enclosed in double quotes using a much easier method than other posted, and have commented the code completely so that others can also understand it for answering UNC paths as current directories in batch file where admin rights are requested.
The batch script posted there is written to work independent on what is the current directory for working also with batch file being executed from a network share using UNC path which of course works only if the network share is still accessible according to permission settings of the share after elevation to administrator level. I found out today after a comment by Richard on his answer on Open Command Window in Windows x64 mode that the web page SS64 - Run with elevated permissions contains nearly the same code as I developed without having ever read the code there.
The adapted batch file code below should work for this task. It expects the executable
ewfmgr.exe
in same directory as the cmd script orewfmgr.exe
is specified with full path as first argument on executing the script in case of being in a different directory.6. Best solution for this task
But it turned out after I finished writing and testing the code above, writing this long answer and before posting it, reading the comment written by Richard on his answer on Open Command Window in Windows x64 mode, the best solution is most likely using the NSIS code as posted at
How do you request administrator permissions using NSIS?
And use in the command script just the few lines at bottom also posted as my answer on Open Command Window in Windows x64 mode to switch from 32-bit to 64-bit environment.
I'd like to point to an NSIS specific way about dealing with UAC and elevated rights.
If your NSIS installer needs to run anything with elevated permissions, you have to indicate that in your NSIS script like so:
Once you do that, when you start the installer, it will pop up the UAC prompt and in succession won't have any problems running external scripts or programs which need elevated permissions.
This is pretty much in line with #5 of Mofi's answer - I still post this one as I think it boils it down to the need-to-know. NSIS seems to be the show-stopper here for you.
For reference: NSIS - Could not write updated PATH to HKLM