I have a lot of code in a PowerShell script that are mix of commands that need elevation to run and commands that don't, those that need elevation show errors in PowerShell console like:
"You don't have enough permissions to perform the requested operation"
and
"Requested registry access is not allowed."
is there a way to globally suppress only the kinds of errors that PowerShell shows due to lack of necessary privileges?
I thought about a function that checks for elevation and performs actions based on the result, like this:
https://devblogs.microsoft.com/scripting/use-function-to-determine-elevation-of-powershell-console/
Function Test-IsAdmin
{
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal $identity
$principal.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
and
if(-NOT (Test-IsAdmin))
{ write-host "Skipping Admin command" }
else { $code }
but I don't know how to apply it globally to the whole script, so that commands that don't need elevation run, and those that need elevation show a custom message or skip that part silently.
another thing that can help my situation would be to find out if a PowerShell command needs elevation before actually running it and causing it to show errors in console due to lack of privileges.
CodePudding user response:
It seems that errors stemming from a lack of privileges typically - but not necessarily - involve a System.UnauthorizedAccessException
or System.Security.SecurityException
.NET exception behind the scenes, whose name is then reflected as part of the .FullyQualifiedErrorId
property of the resulting PowerShell error record, which is of type System.Management.Automation.ErrorRecord
.
Assuming that this applies to all errors you care about, you can use a (rarely used anymore) trap
statement as follows:
trap {
if ($_.FullyQualifiedErrorId -match 'UnauthorizedAccessException|SecurityException') {
Write-Warning "Skipping admin command ($($_.InvocationInfo.Line.Trim()))"
continue # Suppress the original error and continue.
}
# If the error was created with `throw`, emit the error and abort processing.
# SEE CAVEAT BELOW.
elseif ($_.Exception.WasThrownFromThrowStatement) { break }
# Otherwise: emit the error and continue.
}
# ... your script
Caveat:
If your script implicitly raises script-terminating errors - via
-ErrorAction Stop
or$ErrorActionPreference = 'Stop'
- the above solution in effect turns them into statement-terminating errors and continues execution (only explicit script-terminating errors created with athrow
statement are recognized as such in the code above, and result in the script getting aborted).Unfortunately, as of PowerShell 7.2.x, there is no way to generally discover whether a given error is (a) non-terminating, (b) statement-terminating or (c) script-terminating (fatal).
- See GitHub issue #4781 for a proposal to add properties to [
System.Management.Automation.ErrorRecord
] to allow such discovery in the future.
- See GitHub issue #4781 for a proposal to add properties to [