windowspowershellerror-handlinguac

Detect if user cancel call to elevated prompt in powershell


In powershell script is a call to run another PowerShell script using elevated privileges:

try{
    powershell -ExecutionPolicy Bypass -Command "Start-Process Powershell -Verb RunAs -Wait -ErrorAction Ignore -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File `"path\to\file`"'"
}
catch{
   # I can't get to here - thats my problem!
}

A Windows prompt then asks you: "Do you want to allow this app to make changes to your device?". When accepting, the script runs with elevated privileges, but if the user cancel in this prompt, an error occur. But in the latter case, I can't catch the cancel. It just gives an error and then continues the script.

Is there by any means a way to catch the error (in the try/catch block), when the user cancel? Here I've put the -errorAction Ignore in the Start-Process, but whatever errorAction I choose I can't catch the error. I've also tried to add an errorAction with the first part of the call (powershell -ExecutionPolicy Bypass -errorAction Ignore ...) with another no-catched error as a result. You can't use the errorAction here ...

Do you have any idea of how to call this script with elevated privileges and catch if the user cancel the Windows prompt?


Solution

    • Calls to external programs do not integrate with PowerShell's error-handling system, invariably in Windows PowerShell and in PowerShell (Core) up to version 7.3.x and by default in v7.4+, so you cannot use try / catch with a call to an external program such as powershell.exe.

    • However, given that you're calling from PowerShell, there is no no need to call via powershell.exe, the Windows PowerShell CLI.

      • That is, unless you're running PowerShell (Core) and must explicitly call Windows PowerShell - but here, since you need a CLI call via Start-Process -Verb RunAs in order to achieve elevation anyway - you're free to choose either CLI executable, i.e. you can alternatively call pwsh.exe, the PowerShell (Core) CLI.
      • If you want to call the same PowerShell executable that underlies the current session, use (Get-Process -Id $PID).Path
    try{
      # Call Start-Process directly.
      # If the user cancels the UAC prompt, a statement-terminating error
      # occurs, which (silently) triggers the `catch` block.
      Start-Process powershell Verb RunAs -Wait -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File "path\to\file"'
    }
    catch{
       Write-Warning "User canceled UAC prompt."
    }