Batch calls admin batch, vabiable doesn't cross over

Viewed 101

I am trying to send a variable from one batch file to another after elevating privileges. Test2.bat doesn't echo test123, it just echos that ECHO is on.

test1.bat

set "test=test123"
call "%cd%\test2.bat"
pause

test2.bat

:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------

echo %test%
pause
3 Answers

You are setting a variable, then you are elevating and creating a new process and you expect the variable to exist. instead call test2.bat from test1.bat but let it set the variable after it got the privileges, but returning to call test1.bat..

@echo off
set "test=test123"
if not "%~1" == "haveAdmin" call "%~dp0\test2.bat"

then test2.bat some minor changes, see if you can spot them:

@echo off
:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if %errorlevel% NEQ 0 (
    echo Requesting administrative privileges...
    goto UACPrompt
) else (
    goto gotAdmin
)

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%~dp0"
    call test1.bat haveAdmin
:--------------------------------------
echo %test%
pause

Your code fails because the VBScript is creating a new separate process when prompting UAC.

If you only want to pass one single variable with very simple content (without embedded ', ", CRLF...), the easiest way is to pass as it as a parameter.

test-call.bat

@echo off
set "test=test_123!" only works for simple content
call "%__CD__%admin.bat" %test%

admin.bat

@echo off


if "%~1" == "" exit /b 1
("%__APPDIR__%net.exe" session||(
    "%__APPDIR__%WindowsPowerShell\v1.0\powershell.exe" -NoProfile -NonInteractive -Command "Start-Process -FilePath '%~f0' -ArgumentList '%~1' -Verb Runas"
    exit /b
))>nul 2>&1


set "var=%~1"
====SETLOCAL EnableDelayedExpansion
echo(!var!
pause

If your code involves parsing multiple (all) variables or tricky content, the best way is to let Start-Process return to the caller itself.

How about passing the batch file as parameter?

Test1.bat

set "test=test123"
 "%cd%\test2.bat" "%test%"
pause

Test2.bat

@echo off
set "test=%~1"
:: BatchGotAdmin
:-------------------------------------
REM  --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"

REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
    echo Requesting administrative privileges...
    goto UACPrompt
) else ( goto gotAdmin )

:UACPrompt
    echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
    echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"

    "%temp%\getadmin.vbs"
    exit /B

:gotAdmin
    if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
    pushd "%CD%"
    CD /D "%~dp0"
:--------------------------------------

echo %test%
pause
Related