# To create an *alias* for this function that conforms to PowerShell's naming # standard, use, e.g.: # Set-Alias iwe Invoke-WithErrorHandling. function Invoke-WithErrorHandling { # Parse the arguments into the executable and the pass-through arguments # for it. $exe, $argsForExe = $Args # Workaround for v7.2-: # Prevents 2> redirections applied to calls to this function # from accidentally triggering a terminating error in PS v7.2- # See bug report at https://github.com/PowerShell/PowerShell/issues/4002 $ErrorActionPreference = 'Continue' # In v7.4+, prevent PowerShell itself from emitting an error in response # to a nonzero exit code reported from a program. $PSNativeCommandUseErrorActionPreference = $false try { if ($MyInvocation.ExpectingInput) { # Relay pipeline input. Note: The input is collected first, in full, # up front, before it is relayed to the target executable. # Also, the v7.4+ ability to pipe raw bytes between two external # executables is unavailable due to using this wrapper function. $input | & $exe $argsForExe } else { & $exe $argsForExe } } catch { throw } # catch is triggered ONLY if $exe can't be found, never for errors reported by $exe itself if ($LASTEXITCODE) { throw "`"$exe`" indicated failure (exit code $LASTEXITCODE)." } } - The following function therefore expects a single, mandatory script-block argument containing the command to execute (and optionally also pipeline input), so that in order to make it execute
git foo, you'd call it as
Invoke-WithErrorHandling { git foo }
# To create an *alias* for this function that conforms to PowerShell's naming # conventions, use, e.g.: # Set-Alias iwe Invoke-WithErrorHandling. function Invoke-WithErrorHandling { param( [Parameter(Mandatory, Position=0)] [scriptblock] $ScriptBlock, [Parameter(ValueFromPipeline)] # Optional pipeline input $InputObject ) begin { # Set up a steppable pipeline. $steppablePipeline = $ScriptBlock.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) # Workaround for v7.2-: # Prevents 2> redirections applied to calls to this function # from accidentally triggering a terminating error in PS v7.2- # See bug report at https://github.com/PowerShell/PowerShell/issues/4002 $ErrorActionPreference = 'Continue' # In v7.4+, prevent PowerShell itself from emitting an error in response # to a nonzero exit code reported from a program. $PSNativeCommandUseErrorActionPreference = $false try {} if ($MyInvocation.ExpectingInput)process { # Relay pipelinePass input.the Note:current Thepipeline input is collected first, in full, # up front, before it is relayed to the target executablethrough. # Also, the v7.4+ ability to pipe raw bytes between twotry external{ # executables is unavailable due to using this wrapper function$steppablePipeline. $input | & $ScriptBlockProcess($_) } else { & $ScriptBlock } } catch { throw } # catch is triggered ONLY if $exe can't} be found,end never{ for errors reported by$steppablePipeline.End() $exe itself if ($LASTEXITCODE) { throw "`"$ScriptBlock`" indicated failure (exit code $LASTEXITCODE)." } } } Unlike the earlier function, this one is an advanced one, which is unproblematic, because the one and only argument specifying the command line to execute cannot collide with common parameters anymore. However, common parameters such as
-OutVariableand-ErrorVariabledo not function properly, due to the design limitation discussed in GitHub issue #5758The notes on the earlier function apply to this one too, except that pipeline input is supported in a streaming fashion by this function (no need to collect all input up front first), by virtue of it being implemented as a proxy (wrapper) function - see this answer for additional information.