-1

The batch hybrid script below aims to auto invoke Administrator privileges before running some tasks requiring elevated rights. It does popup the UAC prompt, but regardless of the user choice Admin privileges aren't granted.

I wonder if Window's ShellExecute function used in it can accept WSF arguments or other expandable parameters? In this case its the batch file name. If it can, how the script should be changed for that without restructuring aimed at using a different method?

<!-- : Begin batch script
@echo off
setlocal EnableExtensions EnableDelayedExpansion
CD /D "%~dp0" & echo "%*"
set "dir=%temp%\Unzip"
set "file=%USERPROFILE%\Downloads\archive.zip"
if not "%1"=="ADR" (call :GetAdminRights
    if defined adm cscript //nologo "%~f0?.wsf" //job:ADM "%~nx0")
>nul 2>&1 net file && (echo/ & echo "!errorlevel!") || ^
(echo/ & echo "!errorlevel!" & goto :end)

:: add your code here
echo Performing admin tasks
echo Hello >C:\test.txt

:end
timeout 5
exit /b

:GetAdminRights
REM Check for permissions
>nul 2>&1 net file
REM If error flag set, user don't have admin permissions
if '!errorlevel!' NEQ '0' (echo Requesting administrative privileges...
    set "adm=0"
    echo/ & echo "!errorlevel!" "%~nx0" "%~dp0" & echo/)
exit /b

----- Begin wsf script --->
<package>
    <job id="ADM"><script language="VBScript">
        Set UAC = CreateObject("Shell.Application") 
        WScript.Echo wscript.Arguments(0)
        UAC.ShellExecute "cmd.exe", "/c ""wscript.Arguments(0)"" ADR", "", "runas", 1 
    </script></job>
</package>  

:: Error in UAC Prompt (shown in details. Can't expand batch name correctly.)
Program location: "C:\Windows\System32\cmd.exe /c "wscript.Arguments(0)" ADR
sambul35
  • 1,058
  • 14
  • 22
  • Why does your script need administrator permissions? – Bill_Stewart Jul 29 '16 at 15:00
  • @Bill_Stewart I edited the question to give an example of such requirement. However, I'm more interested to learn ShellExecute limitations rather than find "any" possible way to accomplish the task. :) – sambul35 Jul 29 '16 at 15:12
  • I don't see where you say why you need administrator permissions. You just say "before running some user tasks." What tasks? (User tasks should not require administrator permissions.) – Bill_Stewart Jul 29 '16 at 15:29
  • @Bill_Stewart I edited the text. Examples of admin tasks IMO aren't essential to my question, but I gave an example in the code as you asked, like saving a file to C: drive. Now would you be able to directly answer this question about ShellExecute function limitations. :) – sambul35 Jul 29 '16 at 15:36
  • I would recommend not using batch/WSF and use PowerShell instead. – Bill_Stewart Jul 29 '16 at 15:38
  • @Bill_Stewart Thank you! Of course you can provide more details or links about the suggested solution if you want. :) – sambul35 Jul 29 '16 at 15:41
  • I would use the awesome [nircmd](http://www.nirsoft.net/utils/nircmd2.html#elevate): `nircmdc elevate "%~0" ADR .......` - it has many other useful functions, including `runas`. – wOxxOm Jul 30 '16 at 14:16
  • @wOxxOm Thanks. I already derived a native simple way to [elevate privileges](http://stackoverflow.com/questions/38642927/simple-method-to-run-a-batch-as-administrator-using-javascript/38650025#38650025) in a batch, but rather wanted to figure out the limitations of ShellExecute native shell function, and possible workarounds. One workaround is of course echo the VBS script section to a file. But I prefer the hybrid batch format that works faster. :) – sambul35 Jul 30 '16 at 15:42
  • Well, I think nircmd is MUCH easier and faster... – wOxxOm Jul 30 '16 at 16:04
  • @wOxxOm Possibly. But the problem with using 3rd party utilities is we'd need to add them for just about every task instead of using native Windows or scripting language functionality. I don't think its a good approach for developers. – sambul35 Jul 30 '16 at 16:11

2 Answers2

0

Yes, it can. The trick is to submit in the cscript call all Cmd.exe arguments required to restart Cmd in Administrator mode, and read them properly in the WSF section of the batch.

<!-- : Begin batch script
@echo off
setlocal EnableExtensions EnableDelayedExpansion
CD /D "%~dp0" & echo "%*"
set "dir=%temp%\Unzip" & set "file=%USERPROFILE%\Downloads\archive.zip"
if not "%1"=="ADR" (call :GetAdminRights
    if defined adm cscript //nologo "%~f0?.wsf" //job:ADM "/c" "%~sf0" "ADR" )
echo/ & >nul 2>&1 net file && (echo "!errorlevel!" Got admin rights & echo/) ^
 || (echo "!errorlevel!" No admin rights & goto :end)

:: add your code here
echo Performing admin tasks
echo Hello >C:\tst.txt

:end
timeout /t 5 >nul
exit /b

:GetAdminRights
REM Check for permissions
echo/ & >nul 2>&1 net session && (echo Got admin rights) ^
 || (echo No admin rights) & echo/
REM If error flag set, user don't have admin permissions
if '!errorlevel!' NEQ '0' (echo Requesting admin rights...
    set "adm=0" & echo/ & echo "!errorlevel!" "%~nx0" "%~dp0" & echo/)
exit /b

----- Begin wsf script --->
<package>
    <job id="ADM"><script language="VBScript">
        Set UAC = CreateObject("Shell.Application") 
        args = "" 
        For Each strArg in WScript.Arguments
        args = args & strArg & " "  
        Next 
        WScript.Echo args
        UAC.ShellExecute "cmd.exe", args, "", "runas", 1 
    </script></job>
</package>  
sambul35
  • 1,058
  • 14
  • 22
0

Here is a batch script 'Elevate.bat' to execute as Administrator any command passed in arguments string. If the command contains special characters, escape them by '^'. For instance:

Elevate whoami /groups ^| find "S-1-16-12288"`

Elevate.bat:

    <!-- : --- Self-Elevating Batch Script ---------------------------
    @whoami /groups | find "S-1-16-12288" > nul && goto :admin
    @set "ELEVATE_CMDLINE=cd /d "%cd%" & call "%~f0" %*"
    @cscript //nologo "%~f0?.wsf" //job:Elevate & exit /b

    -->
    <job id="Elevate"><script language="VBScript">
      Set objShell = CreateObject("Shell.Application")
      Set objWshShell = WScript.CreateObject("WScript.Shell")
      Set objWshProcessEnv = objWshShell.Environment("PROCESS")
      strCommandLine = Trim(objWshProcessEnv("ELEVATE_CMDLINE"))
      objShell.ShellExecute "cmd", "/c " & strCommandLine, "", "runas"
    </script></job>
    :admin -----------------------------------------------------------

    @echo off
    echo Running as elevated user.
    echo Script file : %~f0
    echo Arguments   : %*
    echo Working dir : %cd%
    echo.
    :: administrator commands here
    :: e.g., run shell as admin
    %*
    pause

I use it to create symbolic links like this:

Elevate.bat mklink /d common g:\PerforceData\devel\common
Elevate.bat mklink build.xml g:\PerforceData\devel\build.xml
Alex F
  • 1
  • 2