Controlling Admin PowerShell from Non-Elevated PowerShell

by Jun 28, 2013

In a previous tip we illustrated how you can use Start-Process to launch an elevated PowerShell from within your script to do elevated tasks.

The problem with launching elevated processes is, though, that the non-elevated caller cannot monitor the elevated process. So there is (typically) no way for your non-elevated PowerShell to find out when the elevated PowerShell has finished.

Here's a creative approach that allows you to launch an elevated PowerShell and wait for it to complete. It also hides the elevated PowerShell window. As a proof, the elevated PowerShell creates a Registry key in HKLM:

# code to execute with admin privileges (including some artificial delay):
$code = { New-Item -Path HKLM:\Software\Testkey -ErrorAction SilentlyContinue; Start-Sleep -Seconds 4 }

# execute PowerShell with admin privileges:
$handle = Start-Process -FilePath powershell.exe -Verb RunAs -ArgumentList $Code -PassThru -WindowStyle Minimized

# waiting for the process to exit:
while ($handle.HasExited -ne $True)
Start-Sleep -Milliseconds 300

"Admin job completed."

Note that the code in $code contains a Start-Sleep statement. It's delaying the code so you can better watch your non-elevated PowerShell to wait for the elevated task to complete.

To monitor the elevated process, the non-elevated PowerShell asks Start-Process to return a process object (-PassThru). Since the process object represents an elevated process, most of its properties are invisible to the calling non-elevated process for security reasons. This includes the property HasExited. It returns $null.

However, once the elevated process is terminated, the protection is taken away, and now HasExited returns $true. That's what the non-elevated script can use to check whether the elevated process still runs or has exited.

Twitter This Tip! ReTweet this Tip!