Skip to content

Instantly share code, notes, and snippets.

@JustinGrote
Last active January 24, 2025 10:28
Show Gist options
  • Save JustinGrote/a21072f82104819295bc6b89abd56847 to your computer and use it in GitHub Desktop.
Save JustinGrote/a21072f82104819295bc6b89abd56847 to your computer and use it in GitHub Desktop.
A powershell throw alternative that uses the parent context for the stacktrace that is more user-friendly. Useful as a private function in powershell modules.
using namespace System.Management.Automation
function ThrowUser {
<#
.SYNOPSIS
Throws a terminating exception record that shows the cmdlet as the source of the error, rather than the inner "throw". Makes for more user friendly errors than simply using "throw"
.INPUTS
[String]
[Exception]
[Object]
.OUTPUTS
[Management.Automation.ErrorRecord]
.LINK
https://powershellexplained.com/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/ - Section on $PSCmdlet.ThrowTerminatingError()
.EXAMPLE
ThrowUser "Some Error Occured"
.EXAMPLE
ThrowUser [System.ApplicationException]
.EXAMPLE
ThrowUser -Exception [System.ApplicationException] -ErrorCategory ConnectionError -Target 'ping.exe' -ErrorID 'CouldNotResolveDnsName'
#>
[CmdletBinding()]
param (
[Parameter(Mandatory)]$InputObject
)
#Generate an error record from "throw"
try {
throw $InputObject
} catch {
$errorRecord = $PSItem
}
#Because this command is itself a cmdlet, we need the parent Cmdlet "context" to show the proper line numbers of the error, which is why scope 1 is used. If that doesn't exist then just use normal scope
try {
$myPSContext = (Get-Variable -Scope 1 'PSCmdlet' -Erroraction Stop).Value
} catch [ItemNotFoundException] {
$myPSContext = $PSCmdlet
}
$myPSContext.ThrowTerminatingError($errorRecord)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment