2

say I have the following script test-exception.ps1

[CmdletBinding()]
    param()

process {
    1/0
}

if I run it, I get

Tentative de division par zéro.
Au caractère U:\test-exception.ps1:5 : 2
+     1/0
+     ~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

if now I try/catch the error,

[CmdletBinding()]
    param()

process {
    try {
        1/0
    } catch {
        write-error $_
    }
}

I get

Au caractère Ligne:1 : 1
+ U:\test-exception.ps1
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,test-exception.ps1

where I lose the line number and the line text. I tried many variants but the only way I've found to get the first error message in the error stream of a surrounding CMD while try/catching the code (I want to be able to exit with some custom exit code, not 1) is

[CmdletBinding()]
    param()

process {
    try {
        1/0
    } catch {
        [Console]::Error.WriteLine(($_ | Out-String))
        exit 99
    }
}

did I miss something or is this the only solution?

1 Answer 1

1

As you have noticed, when you call Write-Error in a catch block, the error message only shows the origin of the Write-Error call, not the origin of the exception.

You could get the origin of the exception from the PositionMessage property of ErrorRecord.InvocationInfo, but a far easier way is to just pipe the ErrorRecord object ($_) to Out-String.

In addition you may show the script stack trace by querying the ErrorRecord.ScriptStackTrace property, which contains the chain of function calls that led to the error.

Finally, set the ErrorRecord.ErrorDetails property to override the default error message so all the information about the original error will be shown.

try {
    1/0
} catch {
    $_.ErrorDetails = ($_ | Out-String) +
                      "`n------- SCRIPT STACKTRACE -------`n$($_.ScriptStackTrace)" +
                      "`n `n------- CAUGHT AT -------"
    Write-Error $_
}

Output:

C:\Test\ExceptionTest.ps1 : Attempted to divide by zero.
In C:\Test\ExceptionTest.ps1:4 Char:2
+     1/0
+     ~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException
 
------- SCRIPT STACKTRACE -------
at <ScriptBlock>, C:\Test\ExceptionTest.ps1: Line 4
at <ScriptBlock>, <no file>: Line 1
 
------- CAUGHT AT -------
In Line:1 Char:1
+ . 'C:\Test\ExceptionTest.ps1'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,ExceptionTest.ps1

The information shown after the "CAUGHT AT" line is still pretty useless, but I don't think we can do anything about that, as it is added automatically by PowerShell. At least the relevant information is shown at the top now.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.