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:
Specifically, the Command we feed Powershell ( "Start-Process cmd \"/k %~dpnx0\" -Verb RunAs" ) is telling Powershell to:
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.
And the selectable Mini:
@( ( NET SESSION 2>&1 >NUL ) || ( powershell.exe -Command "Start-Process cmd \"/k %~dpnx0\" -Verb RunAs" GOTO :EOF ) )
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! :)
-- 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
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!
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! :)