Solved How to run Batch File as Admin?

Thanks for joining usernamewastake.
You won't regret doing so.


Im glad you found that command line useful, Usernamewastake.

I've since shortened the 'prompt for Admin rights' line, and have also created a faster version of the one-liner, one which uses VBScript, I will share here for anyone to use:

(add these lines just under the "@echo off" in your batch files)

Using PowerShell
Same line as seen in post #18, only shorter. This is currently the shortest known method for promoting a UAC dialogue in batch. Though there's small caveat: red text can be seen briefly on the Cmd screen upon a user declining the UAC dialogue.​
Code:
net sess>NUL 2>&1||(powershell saps '%0'-Verb RunAs&exit)

Below is the same as the above, but no red text will appear upon the user declining the UAC dialogue.​
Code:
net sess>NUL 2>&1||(powershell try{saps '%0'-Verb RunAs}catch{}&exit)


Using VBScript
About 4 times faster than the PowerShell method. Though very briefly makes use of a temporary file.​
Code:
net sess>NUL 2>&1||(echo.CreateObject^("Shell.Application"^).ShellExecute"%~0",,,"RunAs",1 >"%TEMP%\%~nx0.vbs"&WScript "%TEMP%\%~nx0.vbs"&del "%TEMP%\%~nx0.vbs"&exit)
 

My Computer

Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
ElevateScript

The command lines in my previous post work fine, however, like many other solutions to this problem found on the Internet, the UAC window that pops up is not in focus—most UAC dialogues are.

The below ':PromptUacAndFocus' batch function focuses and brings the UAC dialogue window to the front.


Edit: Updated and offically renamed to "ForceElevation", the new function now preserves arguments passed to the script!


Edit 2016-09-22: Renamed function “ElevateScript”.


ElevateScript.bat
Code:
@echo off
goto :main

:ElevateScript [Args]
setlocal
	set "args=%*"
	if defined ARGS set "args=%ARGS:"=""%"
	set "temp1="%TEMP%\%~nx0_1_%RANDOM%.vbs""
	set "temp2="%TEMP%\%~nx0_2_%RANDOM%.vbs""
	net sess >NUL 2>&1||(
		> %TEMP1% (
			echo CreateObject^("Shell.Application"^).ShellExecute "%COMSPEC%","/c """"%~f0"" %ARGS%""",,"RunAs",1
		)
		> %TEMP2% (
			echo strTmpFile_1 = %TEMP1%
			echo strTmpFile_2 = %TEMP2%& echo(
			echo Function CountWindowInstance^(strProcessName^)
			echo 	CountWindowInstance = GetObject^("winmgmts:\\.\root\cimv2"^).ExecQuery _
			echo 	^("Select * from Win32_Process Where Name = '" ^& strProcessName ^& "'"^).Count
			echo End Function& echo(
			echo Set WshShell = CreateObject^("WScript.Shell"^)& echo(
			echo WScript.Sleep 100
			echo For I = 0 To 2
			echo 	If CountWindowInstance^("consent.exe"^) ^> 1 Then WScript.Sleep 200
			echo 	WshShell.AppActivate^("User Account Control"^)
			echo Next& echo(
			echo With CreateObject^("Scripting.FileSystemObject"^)
			echo 	If .FileExists^(strTmpFile_1^) Then .DeleteFile^(strTmpFile_1^)
			echo 	If .FileExists^(strTmpFile_2^) Then .DeleteFile^(strTmpFile_2^)
			echo End With
		)
		start WScript %TEMP1% | start WScript %TEMP2%
		exit
	)
endlocal
goto :eof

:main
call :ElevateScript %*

REM Test if script is running elevated
>NUL 2>&1 net sess && (
	echo This script has administrative privileges!
) || (
	echo This script does not have administrative privileges.
)
pause
 
Last edited:

My Computer

Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
Hi Pyprohly,

I'm looking for some Help with regards to this solution. As far as gaining Admin Rights to run the batch it is working perfectly by my problem is that I'm passing a parameter to the batch file. Basically I am sending file names to the Batch file Via the sendto context menu in explorer but I am losing this information as the session is reopened with the admin user. Is there a way I can pass this information to the admin session?

Thanks in Advance,

T.
 
Last edited by a moderator:

My Computer

Computer type
Laptop
Computer Manufacturer/Model Number
Dell Inc. Latitude E5440 01
OS
Windows 7 Enterprise (x64) Service Pack 1 (build 7601)
CPU
2.70 gigahertz Intel Core i7-4600U
Motherboard
Dell Inc. 08RCYC A00
Memory
8098 Megabytes Usable Installed Memory
Graphics Card(s)
NVIDIA GeForce GT 720M
Monitor(s) Displays
2 X DELL P2011H
Screen Resolution
(1600 X 900), (1600 X 900)
Hard Drives
Seagate ST500LM000-1EJ162 encrypted with McAfee
Keyboard
Standard PS/2 Keyboard
Mouse
Dell Touchpad
Welcome to SevenForums Tr3Jack,

I thank you for adopting my solution regarding this topic.

[M]y problem is that I'm passing [an argument] to the batch file [...] but I am losing this information as the session is reopened with the admin user. Is there a way I can pass this information to the admin session?
Yes, there is a way to preserve passed arguments...

In truth, an updated version of that elevation function I offer is sitting on my computer, picking up digital dust. The reason why I haven't updated the ":PromptUacAndFocus" function to support passed arguments, in this thread, is because I was never able to come up with a clean way to get it to be compatible with the usual poisonous characters: &, <, >, and |.

This may not be a huge concern though; the ampersand is the only real one to worry about. As long as none of your file names contain '&', the new ":ForceElevation" I'm about to replace my ":PromptUacAndFocus" function with, in post #22, will seamlessly implement an elevation function that does not eat your arguments.
 
Last edited:

My Computer

Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
Pyprohly,

Thanks for the updated solution. I tried it today and it is working perfectly for me. :D
Your support is very much appreciated.

T..
 

My Computer

Computer type
Laptop
Computer Manufacturer/Model Number
Dell Inc. Latitude E5440 01
OS
Windows 7 Enterprise (x64) Service Pack 1 (build 7601)
CPU
2.70 gigahertz Intel Core i7-4600U
Motherboard
Dell Inc. 08RCYC A00
Memory
8098 Megabytes Usable Installed Memory
Graphics Card(s)
NVIDIA GeForce GT 720M
Monitor(s) Displays
2 X DELL P2011H
Screen Resolution
(1600 X 900), (1600 X 900)
Hard Drives
Seagate ST500LM000-1EJ162 encrypted with McAfee
Keyboard
Standard PS/2 Keyboard
Mouse
Dell Touchpad
ForceElevate

   Note
This method has been patched following the Creators Update in Windows 10.


I’m not sure why I called it “ForceElevation”—it asks for elevation rather politely—so I’ve renamed the function more appropriately: “ElevateScript”. And here’s my new attempt at a ForceElevation function...

Introducing ForceElevate! This batch function implements a simple method for invoking any command with elevated rights from a non-elevated host, silently, bypassing UAC prompting where possible.

This was made possible by Matt Nelson’s (enigma0x3) recent discovery of a (the first ever) file-less UAC bypass technique. For details about how this was discovered and how it works, see Enigma0x3’s blog post about the topic here.

My new batch function can be used to create a self-elevating script, like my previous ElevateScript function, minus the UAC prompting. See examples 2 and 3 below for how you may incorporate this functionality into your own scripts using the new function.

Some caveats about ForceElevate to be noted:
  • ForceElevate will not suceed if UAC is set to “Always notify” (the highest setting). The user will be presented a UAC prompt if so, for each time the function is called in the script. See example 3 for a demonstration of how to check whether ForceElevate will run successfully prior to calling it.
  • As the technique involves a registry key hijacking, ForceElevate requires a very short cool down after use. In this period, another batch file using the function at the same time may fail. As such, this function is not suitable where many scripts, in need of elevated privileges, have to be run together.
  • The commands run by ForceElevate will always run in a new context, rather than the invoking host.

ForceElevate
Code:
:ForceElevate Command*
:: v1.0
setlocal
	set "command=%*"
	if "%COMMAND:"=%"=="" exit /b 1
	set "command="%%ComSpec%%" /c "start cmd.exe /c "%COMMAND%"""

	set "mscfile_root_regpath=HKCU\Software\Classes\mscfile"
	set "mscfile_command_regpath=%MSCFILE_ROOT_REGPATH%\shell\open\command"
	set "eventvwr=%WINDIR%\System32\eventvwr.exe"

	>NUL 2>&1 reg query "%MSCFILE_COMMAND_REGPATH%" && (
		>&2 echo The required registry key could not be accessed
		exit /b 75
	) || (
		>NUL reg add "%MSCFILE_COMMAND_REGPATH%" /ve /t REG_EXPAND_SZ /d "%COMMAND:"=\"%" /f
	)

	explorer "%EVENTVWR%"
	pathping -n -p 200 -q 1 127.0.0.1 >NUL
	>NUL reg delete "%MSCFILE_ROOT_REGPATH%" /f

	tasklist /fi "IMAGENAME eq eventvwr.exe" /nh 2>NUL | find /i "eventvwr.exe" >NUL && (
		tskill eventvwr
	)
endlocal
exit /b 0

[SIZE="+1"]Example usages[/SIZE]

Example 1: Running single commands as administrator, bypassing UAC prompting when possible. Assume the script is not already running with elevated privileges.
Code:
@echo off
goto :main

:ForceElevate
	[COLOR="Silver"][function definition here][/COLOR]
exit /b 0

:main

REM Run Diskpart. Window remains open due to application’s nature.
call :ForceElevate diskpart

REM Execute Icacls command. Window quickly expires.
call :ForceElevate icacls file.ex /setintegritylevel high

REM Run Tasklist command, keeping the window open.
call :ForceElevate cmd /k "tasklist"


Example 2: Re-run the current script as administrator, bypassing UAC prompting when possible.
Code:
@echo off
goto :main

:ForceElevate
	[COLOR="Silver"][function definition here][/COLOR]
exit /b 0

:main
>NUL 2>&1 net sess || (
	call :ForceElevate %~f0
	exit
)


REM Test if script is running elevated
>NUL 2>&1 net sess && (
	echo This script has administrative privileges!
) || (
	echo This script does not have administrative privileges.
)


Example 3: Re-run the current script as administrator. If UAC bypass is possible, do so, else ask for elevation using ElevateScript function.
Code:
@echo off
goto :main

:ForceElevate
	[COLOR="Silver"][function definition here][/COLOR]
exit /b 0

:ElevateScript
	[COLOR="Silver"][function definition here][/COLOR]
goto :eof

:TestEventVwrUACBypassPossible
setlocal EnableDelayedExpansion
	>NUL 2>&1 net sess || (
		net user "%USERNAME%" | find "*Administrators" >NUL || (
			exit /b 1
		)
		for /f "tokens=1,2,3" %%I in ('
			reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v ConsentPromptBehaviorAdmin ^| find "ConsentPromptBehaviorAdmin"
		') do (
			set "CPBA=%%~K"
		)
		echo(!CPBA:*x=!| findstr "[1234]" >NUL && (
			exit /b 1
		) || (
			exit /b 0
		)
	)
endlocal
goto :eof

:main
>NUL 2>&1 net sess || call :TestEventVwrUACBypassPossible && (
	call :ForceElevate %~f0
	exit
) || (
	call :ElevateScript
	exit
)


REM Test if script is running elevated
>NUL 2>&1 net sess && (
	echo This script has administrative privileges!
) || (
	echo This script does not have administrative privileges.
)

All commands executed by ForceElevate will always run interactively.


Below is a PowerShell port of ForceElevate: Invoke-EventVwrUACBypass. It is an improvement over Enigma0x3’s original cmdlet, Invoke-EventVwrBypass.

By default, all commands are run as background processes. To run a command interactively, use the -Interactive switch.

PHP:
function Invoke-EventVwrUACBypass {
	[CmdletBinding(SupportsShouldProcess=$true)]
	param (
		[Parameter(Mandatory=$true)]
		[ValidateNotNullOrEmpty()]
		[string]
		$Command,

		[switch]
		$Interactive,

		[switch]
		$Force
	)
	$ErrorActionPreference = 'Stop'

	$mscRegkey = @{
		Path = 'HKCU:\Software\Classes\mscfile'
		CommandPath = 'HKCU:\Software\Classes\mscfile\shell\open\command'
	}

	$eventvwrPath = ([Environment]::GetFolderPath('System')) + '\eventvwr.exe'

	if ($Interactive) {
		$Command = '"%ComSpec%" /c "start cmd.exe /c "' + $Command + '""'
	}

	try {
		if ($Force -or ((Get-ItemProperty -Path $mscRegkey.CommandPath -Name '(default)' -ErrorAction SilentlyContinue) -eq $null)) {
			if ($PSCmdlet.ShouldProcess($mscRegkey.CommandPath, 'Create registry entry')) {
				$null = New-Item $mscRegkey.CommandPath -Force | New-ItemProperty -Name '(default)' -Value $Command -PropertyType ExpandString

				if (Test-Path $mscRegkey.CommandPath) {
					Write-Verbose "Created registry path '$($mscRegkey.CommandPath)'"
				}
			}
		} else {
			Write-Verbose 'Registry key already exists, consider using -Force'
			return
		}

		$eventvwr = @{HasExited = $true}
		if ($PSCmdlet.ShouldProcess($eventvwrPath, 'Start process')) {
			$eventvwr = Start-Process -FilePath $eventvwrPath -PassThru -ErrorAction Stop
			if ($?) {
				Write-Verbose 'Started eventvwr.exe'
			}
		}

		if (!$PSBoundParameters['WhatIf']) {
			$wait = 200
			Write-Verbose "Waiting $wait milliseconds for payload to trigger"
			Start-Sleep -Milliseconds $wait
		}
	}
	finally {
		if (Test-Path $mscRegkey.Path) {
			if ($PSCmdlet.ShouldProcess($mscRegkey.Path, 'Remove registry entry')) {
				Remove-Item $mscRegkey.Path -Recurse -Force
				if ($?) {
					Write-Verbose "Removed registry entry $($mscRegkey.Path)"
				}
			}
		}
	}

	if (!($eventvwr.HasExited)) {
		Stop-Process -Id $eventvwr.Id -ErrorAction SilentlyContinue
		if ($?) {
			Write-Verbose 'Killed running eventvwr process'
		}
	}
}
 
Last edited:

My Computer

Computer type
PC/Desktop
OS
Windows 10, Windows 8.1 Pro, Windows 7 Professional, OS X El Capitan
Back
Top