Call batch file with elevated privileges via PowerShell and retrieve exit code Call batch file with elevated privileges via PowerShell and retrieve exit code powershell powershell

Call batch file with elevated privileges via PowerShell and retrieve exit code


To solve the argument problem, you could use

powershell start-process -wait -verb runas '%0' -argumentlist '/additional-arg %*'

The exit code problem:
The first problem is the line

echo powershell returned %errorlevel%.

This can't work, because it's inside a code block and %errorlevel% will be expanded even before powershell will be called and therefore it is always 1 - the result of openfiles /local ...

But even with delayed expansion, I got always 0, probably because it's the exitcode of the successful runas, that it was able to start your batch.

You could use a work around and store the exitcode in a temporary file

@echo offsetlocal EnableDelayedExpansionecho param=%*openfiles /local >nul 2>&1IF %ERRORLEVEL% EQU 0 (    echo elevated, exit 13    pause    echo 13 > "%temp%\_exitcode.tmp"    rem *** using 14 here to show that it doesn't be stored in errorlevel    exit 14) ELSE (    echo not elevated. trying to elevate.    powershell start-process -wait -verb runas '%0' -argumentlist '/additional-arg %*'    set /p _exitcode= < "%temp%\_exitcode.tmp"    del "%temp%\_exitcode.tmp"    echo powershell returned !_exitcode!, lvl !errorlevel!.)


You aren't putting the PowerShell commands to execute in quotes, and you would do well to use the full path as well as include any arguments to the script. A generic way to invoke this, so it could be copied across scripts, your PowerShell invocation should look like so:

powershell -c "if([bool]'%*'){ Start-Process -Wait -Verb runas '%~dpnx0' -ArgumentList ('%*' -split '\s+') } else { Start-Process -Wait -Verb runas '%~dpnx0' }"

For your needs above, this could be simplified since you know you have arguments passed into the batch file to process:

powershell -c "Start-Process -Wait -Verb runas '%~dpnx0' -ArgumentList '/foo'
  • %~dpnx0 - Automatic batch variable, this is the full path to the current script, including the script name
  • %* - Automatic batch variable, this is all arguments passed into the script.
  • ('%*' -split '\s'): This is a PowerShell expression takes the space-delimited %* variable and splits it on continuous whitespace, returning an array. For simplicity this does have a shortcoming in that it will split on spaces in between double quotes, but the regex can be tuned to account for that if needed.

This answer is worth a read for other automatic batch variables you may find use for in the future.