2

I have an application which is installed in x64. I want to execute this EXE in x64 command prompt.

CASE 1:

If I open the command prompt manually as Admin (Start->Type, cmd.exe->Right click->Run as Administrator) then the EXE works fine. I get the following specifications about the Environment variables using SET command in cmd window:

CommonProgramFiles=c:\Program Files\Common Files
CommonProgramFiles(x86)=c:\Program Files (x86)\Common Files
CommonProgramW6432=c:\Program Files\Common Files
PROCESSOR_ARCHITECTURE=AMD64

CASE 2:

If I open the Command window using a script file which elevates to the Admin rights then the EXE is not found. I get the following values for the environments variables by using SET command:

CommonProgramFiles=c:\Program Files (x86)\Common Files
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_ARCHITEW6432=AMD64
ProgramFiles=c:\Program Files (x86)
ProgramFiles(x86)=c:\Program Files (x86)

winSysFolder=System32

Question: I have to work with Case 2. I think that the discrepancy in the paths of ProgramFiles could be the reason of my EXE not working in the second case. How can I specify in the script that it should be executed in x64 command prompt?

PS: The link to my main problem is here.

References: The script file to elevate to Admin has been taken from Matt's answer given here.

Community
  • 1
  • 1
skm
  • 5,015
  • 8
  • 43
  • 104

2 Answers2

2

It looks like you are using a 32-bit executable to run the batch file with elevated privileges. In this case the batch file is executed with 32-bit cmd.exe in %SystemRoot%\SysWOW64, see the Microsoft articles:

As the batch file is already executed with elevated privileges and just needs to be processed by 64-bit cmd.exe on 64-bit Windows, here are the few lines to make sure that the batch file is executed by 64-bit Windows command processor on 64-bit Windows.

@echo off
if "%ProgramFiles(x86)%" == "" goto MainCode
if not exist %SystemRoot%\Sysnative\cmd.exe goto MainCode
%SystemRoot%\Sysnative\cmd.exe /C "%~f0" %*
goto :EOF

:MainCode
set Program
pause

Put your main batch code below the label :Maincode.

The first IF condition jumps to main batch code if the batch file is running on 32-bit Windows where the environment variable ProgramFiles(x86) does not exist at all.

The second IF condition only executed on 64-bit Windows jumps to main batch code if it cannot find the file %SystemRoot%\Sysnative\cmd.exe because the batch file is processed already by 64-bit cmd.exe.

Sysnative is not a directory. It is a special alias which exists only when 32-bit environment is active on 64-bit Windows. For that reason it is only possible to use, for example, the condition if exist %SystemRoot%\Sysnative\* to check for existence of any file, but not the condition if exist %SystemRoot%\Sysnative to check for existence of the directory because of Sysnative is not a directory.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • cmd /?
  • echo /?
  • goto /?
  • if /?
  • pause /?
  • set /?
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Thanks a lot, I think it has solved my problem but will update after testing it on my windows embedded system. – skm Jan 05 '17 at 19:14
1

The simplest way is to use the SysNative path. Here is a modified version of your RunAsAdmin.cmd (which was originally posted here: How can I auto-elevate my batch file, so that it requests from UAC administrator rights if required?) that does that:

::::::::::::::::::::::::::::::::::::::::::::
:: 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
 IF EXIST %SystemRoot%\SysNative\cmd.exe set winSysFolder=SysNative
 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
Community
  • 1
  • 1
Richard
  • 1,121
  • 1
  • 9
  • 15
  • Plagiarized from [Matt's post](http://stackoverflow.com/a/12264592/17034), proper attribution is required by the site license. – Hans Passant Jan 05 '17 at 16:14
  • 1
    As I already told Mofi, it came from skm's original question. I didn't realise it had been posted before that. Since you've provided a link to the original, I've included that in my answer now. – Richard Jan 05 '17 at 16:19
  • Well, Matt's code does not work if the batch file is executed with 1 or more parameters enclosed in double quotes because of the parameter strings contain 1 or more spaces. For example inserting above the line with `exit /B` the line `echo %* & pause`, replacing `ewfmgr c: -enable` by `echo %*`, running this batch file with `"%ProgramFiles%" "hello world"` and clicking on button Yes on elevation prompt results in two console windows. The bottom one is from initial call with correct arguments list, and the top one is the elevated one with wrong arguments list because double quotes lost. – Mofi Jan 05 '17 at 16:32
  • But the code works if the batch file is initially called with no parameters or only with parameter strings not enclosed in double quotes because of not containing characters which require the usage of double quotes. By the way: Usage of `set cmdInvoke=1` is not possible with code as posted by [Richard](http://stackoverflow.com/users/6718853/richard) as this results in error message `Windows cannot find 'C:\Windows\SysNative\cmd.exe'` even when started from within 32-bit environment. [skm](http://stackoverflow.com/users/2386113/skm) should have chosen something better than code written by Matt. – Mofi Jan 05 '17 at 16:40
  • 1
    The script on ss64.com includes code to deal with quoted arguments: http://ss64.com/vb/syntax-elevate.html Or, since skm is using NSIS anyway, it would be much simpler to use that to request admin rights: http://stackoverflow.com/questions/8732019/how-do-you-request-administrator-permissions-using-nsis – Richard Jan 05 '17 at 16:54
  • @Richard Those two web page references are really worth an upvote. Best is definitely elevating to administrator level within NSIS. I wondered myself already why an installer should not have such a feature. I'm not familiar with NSIS installer and did not search. Richard, thanks for searching. – Mofi Jan 05 '17 at 19:43