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 $handle.Id # 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.