<

How-To: Have Batch / CMD Script, Initially Run Without Elevation, Automatically Restart in Elevated "Admin" CMD Session.

Published on
3,037 Points
37 Views
Last Modified:
Ben Personick (Previously QCubed)
Nothing is more fun than being able to do what others think can't be done.
This is a simple method I use to have a script run in a non-admin cmd prompt relaunch itself in an admin cmd prompt.

No more manual intervention!

This is a simple function you can add to to the top of any CMD script and call to do the needful.

Well, I have been avoiding writing articles, I didn't think most people read them, and I am far from eloquent, but here goes:


So, We've all had this problem:


 We're going to run a cmd script on a hundred or so systems, and it needs to do a few interactive Steps, and it's just going to be easier to hand out a cmd script which will do most of the needful, and have each of your team click next on a few slides and verify the process didn;t have any errors than make a fully automated solution or do it all by hand. so we just want to get something done quick and dirty.


 However, as we start going forward we realise we can;t just paste the UNC path to the script into the cmd prompt on eahc computer in a big loop around to come back to finish clicking next because oops, we need to apply some routes or something and of course that requires elevation and now we have some guys realising he problem and doing extra steps and we have others who are just not even realising everything is screwed up just reporting the system s erroreed and needing you to look at them.  Ugh.


 Wouldn't it be great if you could just edit the existing script on the UNC path and ask everyone to re-run it without having to explain anything or human error missing, just have the CMD Script check if it is running in an elevated CMD prompt, and relaunch itself in one if it wasn't already on one automatically for us? Yes!  Yes, it would!  


And HERE is how you achieve that:


First, check if you are in an elevated cmd prompt.

 Net Session will error if you are not in an elevated cmd prompt.


 But that just tells you aren't in an elevated cmd prompt, now what?


 Now we change that into a logical test so that we can see if it failed. (We only care if it fails, because otherwise, we're in an elevated prompt.)

 By using the Double Pipe "||" here we can test for a failure of the Net Session CMD as a true-false test, || fires on False (failed state) and && fires on true (Success) state.


  Okay you're still just alerting us here and continuing on, I thought you were going to re-run the script, just the above will not be enough.


  Yes, hold your horses, I'm getting there, I swear!  I'm just making certain to explain exactly what each part of the total function is doing step by step so that it's clear for everyone. :)


  In this next step, we'll see the full function altogether!  (See?)


  ** - A Normal Code window Appears below the following explanation. - **

  * - Only lines with black o Red Characters are required, that minimal version is also given below. *


  Okay, Wow, Awesome!.. But what am I looking at here?


  Alright, Let me break down the trick:


  • You can use a NON-Administrative CMD Shell to Call Powershell.
  • Powershell can be fed a command using the "-Command" switch
    • Which will bypass any checking for execution levels or anything like that (very nice).
  • We then Feed it the Job of Starting a new CMD Instance using the "-Verb RunAs"
  • And it feeds that command Session the cmd method of giving the currently executing scripts full file path and name "%~dpnx0"


  Specifically, the Command we feed Powershell ( "Start-Process cmd \"/k %~dpnx0\" -Verb RunAs" ) is telling Powershell to:


  1. Start "Start-Process" a new copy of the CMD Prompt "CMD"
  2. Open it as a separate session that will stick around "/k"
  3. Feed that session the Script Current path and filename "%~dpnx0"
  4. And to open CMD as an elevated cmd prompt  "-Verb RunAs"


 By putting the pause after it we leave the original cmd prompt up to notify us that we've had to restart the script in an elevated cmd prompt.  ( This is optional, but a nice have, so you know the script is working and relaunching itself. )


 The GOTO :EOF after this is to ensure that the existing script does not continue to execute after relaunching itself. ( This is essential, as you don't want the non-elevated script continuing to run and breaking things. )



Here is the Full Code Snippet so you can copy and paste it to your own work. (I had to take a screenshot of i in the editor, so the Syntax Highlighting colors would display in the example above)


@(
    SETLOCAL ENABLEDELAYEDEXPANSION
    ECHO OFF
    ECHO. Testing For Elevated Command Prompt...
    (
        NET SESSION 2>&1 >NUL
    ) || (
    ECHO.Elevated Command Prompt Not detected, launching batch again in elevated command prompt.
    ECHO. If you are prompted by UAC, accept.
    ECHO. Original batch Script will exit without running further.
    powershell.exe -Command "Start-Process cmd \"/k %~dpnx0\" -Verb RunAs"
    PAUSE
    GOTO :EOF
    )
    COLOR 27
)

REM Your Normal Batch Script Code Goes Here
ECHO.  This Script is Now Executing Code in an Elevated CMD Prompt!
NET SESSION

PAUSE


There you have it!


If you paste this little gem at the start of any script it will do the needful for you.


Here is the minimalist version:

And the selectable Mini:

@(
    (
        NET SESSION 2>&1 >NUL
    ) || (
    powershell.exe -Command "Start-Process cmd \"/k %~dpnx0\" -Verb RunAs"
    GOTO :EOF
    )
)


Notes:


  This does not disable UAC, so you may still have to click "OK" for the UAC Nag screen, but that doesn't break the script!


  There are plenty of ways to Disable UAC, the most common method, and the one I use and advocate is using the UAC Acceptance Exclusion for Administrative Users.*


  *That is set through GPO or Local system Security policy and is outside the scope of this article, but it does not cause CMD and Powershell in Elevated mode, it just disables the NAG when you do so by your own means.


Happy Scripting! :)


~Q



-- Addendum --


Hey!  Wait a Minute!  I have Windows Vista Machines I want to run this on!


Well!  Here is a VB Script Work-Around for Windows Vista!


 ( Thanks to McKnife for sharing this VB Method )


@(
    SETLOCAL ENABLEDELAYEDEXPANSION
    ECHO OFF
    ECHO. Testing For Elevated Command Prompt...
    (
        NET SESSION 2>&1 >NUL
    ) || (
    ECHO.Elevated Command Prompt Not detected, launching batch again in elevated command prompt.
    ECHO. If you are prompted by UAC, accept.
    ECHO. Original batch Script will exit without running further.
    ECHO. CreateObject^("Shell.Application"^).ShellExecute "%~0", "", "", "runas", 1 >"%temp%\runas.vbs"
  "%temp%\runas.vbs"
    PAUSE
    GOTO :EOF
    )
    COLOR 27
)
 ECHO.  This Script is Now Executing Code in an Elevated CMD Prompt! NET SESSION
PAUSE


NOTE: 

Using this method requires writing a Temporary File to the OS.


  Removing this requirement for VB Script is not an easy task as the VBScript Interpreter (CScript) does not accept Commands directly, and instead needs to be provided with a .vbs script.





So to Wrap it up:


Thanks for reading, I hope this has been a helpful learning experience for you!


If this was helpful please Like and comment with any thoughts or suggestions!


  • Know of any other methods to accomplish this? (Perhaps J Script?)


  • Want to help fix the VB Method's flaw of needing to write a file?


If so:


Please comment on the article, or message me directly!


I'll update the article with them and credit you (Unless you prefer not to be credited for some reason, of course.)


Happy Scripting! :)


~Q

0
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Get 7 days free