How can I auto-elevate my batch file, so that it requests from UAC administrator rights if required?

后端 未结 15 898
陌清茗
陌清茗 2020-11-22 03:59

I want my batch file to only run elevated. If not elevated, provide an option for the user to relaunch batch as elevated.

I\'m writing a batch file to set a system v

相关标签:
15条回答
  • 2020-11-22 04:23

    Try this:

    @echo off
    CLS
    :init
    setlocal DisableDelayedExpansion
    set cmdInvoke=1
    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 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 & cd /d %~dp0
    if '%1'=='ELEV' (del "%vbsGetPrivileges%" 1>nul 2>nul  &  shift /1)
    REM Run shell as admin (example) - put here code as you like
    ECHO %batchName% Arguments: P1=%1 P2=%2 P3=%3 P4=%4 P5=%5 P6=%6 P7=%7 P8=%8 P9=%9
    cmd /k
    

    If you need information on that batch file, run the HTML/JS/CSS Snippet:

    document.getElementsByTagName("data")[0].innerHTML="ElevateBatch, version 4, release<br>Required Commands:<ul><li>CLS</li><li>SETLOCAL</li><li>SET</li><li>FOR</li><li>NET</li><li>IF</li><li>ECHO</li><li>GOTO</li><li>EXIT</li><li>DEL</li></ul>It auto-elevates the system and if the user presses No, it just doesn't do anything.<br>This CANNOT be used to create an Elevated Explorer.";
    data{font-family:arial;text-decoration:none}
    <data></data>

    0 讨论(0)
  • 2020-11-22 04:25

    Matt has a great answer, but it strips away any arguments passed to the script. Here is my modification that keeps arguments. I also incorporated Stephen's fix for the working directory problem in Windows 8.

    @ECHO OFF
    setlocal EnableDelayedExpansion
    
    ::net file to test privileges, 1>NUL redirects output, 2>NUL redirects errors
    NET FILE 1>NUL 2>NUL
    if '%errorlevel%' == '0' ( goto START ) else ( goto getPrivileges ) 
    
    :getPrivileges
    if '%1'=='ELEV' ( goto START )
    
    set "batchPath=%~f0"
    set "batchArgs=ELEV"
    
    ::Add quotes to the batch path, if needed
    set "script=%0"
    set script=%script:"=%
    IF '%0'=='!script!' ( GOTO PathQuotesDone )
        set "batchPath=""%batchPath%"""
    :PathQuotesDone
    
    ::Add quotes to the arguments, if needed.
    :ArgLoop
    IF '%1'=='' ( GOTO EndArgLoop ) else ( GOTO AddArg )
        :AddArg
        set "arg=%1"
        set arg=%arg:"=%
        IF '%1'=='!arg!' ( GOTO NoQuotes )
            set "batchArgs=%batchArgs% "%1""
            GOTO QuotesDone
            :NoQuotes
            set "batchArgs=%batchArgs% %1"
        :QuotesDone
        shift
        GOTO ArgLoop
    :EndArgLoop
    
    ::Create and run the vb script to elevate the batch file
    ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\OEgetPrivileges.vbs"
    ECHO UAC.ShellExecute "cmd", "/c ""!batchPath! !batchArgs!""", "", "runas", 1 >> "%temp%\OEgetPrivileges.vbs"
    "%temp%\OEgetPrivileges.vbs" 
    exit /B
    
    :START
    ::Remove the elevation tag and set the correct working directory
    IF '%1'=='ELEV' ( shift /1 )
    cd /d %~dp0
    
    ::Do your adminy thing here...
    
    0 讨论(0)
  • 2020-11-22 04:26

    I wrote gsudo, a sudo for windows: that elevates in the current console (no context switching to a new window), with a credentials cache (reduced UAC popups), and also elevates PowerShell commands.

    It allows to elevate commands that require admin privileges, or the whole batch, if you want. Just prepend gsudo before anything that needs to run elevated.

    Example batch file that elevates itself using gsudo:

    EDIT: New one liner version that works with any windows language and avoids whoami issues:

    net session >nul 2>nul & net session >nul 2>nul || gsudo "%~f0" && exit /b || exit /b
    :: This will run as admin ::
    

    Alternative (original version):

    @echo off
      rem Test if current context is already elevated:
      whoami /groups | findstr /b BUILTIN\Administrators | findstr /c:"Enabled group" 1> nul 2>nul && goto :isadministrator
      echo You are not admin. (yet)
      :: Use gsudo to launch this batch file elevated.
      gsudo "%~f0"
      goto end
    :isadministrator
      echo You are admin.
      echo (Do admin stuff now).
    :end
    

    Install:

    • via chocolatey: choco install gsudo
    • or scoop: scoop install gsudo
    • or grab it from github: https://github.com/gerardog/gsudo

    See gsudo in action: gsudo demo

    0 讨论(0)
  • 2020-11-22 04:27

    If you don’t need to pass arguments through then here’s a compact UAC prompting script that’s a single line long. This does a similar thing as the elevation script in the top voted answer but doesn’t pass arguments through since there’s no foolproof way to do that that handles every possible combination of poison characters.

    net sess>nul 2>&1||(echo(CreateObject("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1:CreateObject("Scripting.FileSystemObject"^).DeleteFile(wsh.ScriptFullName^)>"%temp%\%~nx0.vbs"&start wscript.exe "%temp%\%~nx0.vbs"&exit)
    

    Place this just below the @echo off line in your batch script.

    Explanation

    The net sess>nul 2>&1 part is what checks for elevation. net sess is just shorthand for net session which is a command that returns an error code when the script doesn’t have elevated rights. I got this idea from this SO answer. Most of the answers here use net file instead though which works the same.

    The error level is then checked with the || operator. If the check succeeds then it creates and executes a WScript which re-runs the original batch file but with elevated rights before deleting itself.


    The WScript file is the best approach being fast and reliable, although it uses a temporary file. Here are some other variations and their dis/advantages.

    PowerShell

    net sess>nul 2>&1||(powershell saps '%0'-Verb RunAs&exit)
    

    Pros:

    • Very short.
    • No temporary files.

    Cons:

    • Slow. PowerShell can be very slow to start up.
    • Spews red text when the user declines the UAC prompt. The PowerShell command could be wrapped in a try..catch to prevent this though.

    Mshta WSH script

    net sess>nul 2>&1||(start mshta.exe vbscript:code(close(Execute("CreateObject(""Shell.Application"").ShellExecute""%~0"",,,""RunAs"",1"^)^)^)&exit)
    

    Pros:

    • Fast.
    • No temporary files.

    Cons:

    • Not reliable. Some Windows 10 machines will block the script from running as Windows Defender intercepts it as a potential trojan.
    0 讨论(0)
  • 2020-11-22 04:33

    I am using Matt's excellent answer, but I am seeing a difference between my Windows 7 and Windows 8 systems when running elevated scripts.

    Once the script is elevated on Windows 8, the current directory is set to C:\Windows\system32. Fortunately, there is an easy workaround by changing the current directory to the path of the current script:

    cd /d %~dp0
    

    Note: Use cd /d to make sure drive letter is also changed.

    To test this, you can copy the following to a script. Run normally on either version to see the same result. Run as Admin and see the difference in Windows 8:

    @echo off
    echo Current path is %cd%
    echo Changing directory to the path of the current script
    cd %~dp0
    echo Current path is %cd%
    pause
    
    0 讨论(0)
  • 2020-11-22 04:33

    I use PowerShell to re-launch the script elevated if it's not. Put these lines at the very top of your script.

    net file 1>nul 2>nul && goto :run || powershell -ex unrestricted -Command "Start-Process -Verb RunAs -FilePath '%comspec%' -ArgumentList '/c %~fnx0 %*'"
    goto :eof
    :run
    :: TODO: Put code here that needs elevation
    

    I copied the 'net name' method from @Matt's answer. His answer is much better documented and has error messages and the like. This one has the advantage that PowerShell is already installed and available on Windows 7 and up. No temporary VBScript (*.vbs) files, and you don't have to download tools.

    This method should work without any configuration or setup, as long as your PowerShell execution permissions aren't locked down.

    0 讨论(0)
提交回复
热议问题