Alex Moffitt
Alex Moffitt

Reputation: 126

Capture line number of exception in dot sourced file

So I am running a powershell script within my script, whenever it fails the line number of the exception is the line number of where I call the dot sourced file in my parent script.

I tried to catch the exception, but that didn't contain the full exception, only the actual exception text (no line numbers or categories).

Has anyone solved this? I've been searching high and low and haven't found anything about this.

Upvotes: 1

Views: 385

Answers (1)

trebleCode
trebleCode

Reputation: 2318

Error objects have a number of properties. Output of $Error[0] | Get-Member | Select Name | Set-Clipboard:

Name

Equals
GetHashCode
GetObjectData
GetType
ToString
CategoryInfo
ErrorDetails
Exception
FullyQualifiedErrorId InvocationInfo
PipelineIterationInfo ScriptStackTrace
TargetObject
PSMessageDetails

So, you could throw the details to the console via a function, for example:

Function Write-ErrorDetails($ErrorObject)
{
    $thisError = [PSCustomObject]@{

        Exception = $ErrorObject.Exception
        Message = $ErrorObject.Exception.Message
        FQID = $ErrorObject.FullyQualifiedErrorId
        InovcationInfo = $ErrorObject.InvocationInfo
        ScriptStackTrace = $ErrorObject.ScriptStackTrace
        TargetObject = $ErrorObject.TargetObject
    }

    return $thisError
}

In your script, if you have a try/catch block, you could catch exceptions and call your function:

BEGIN
{
    Function Write-ErrorDetails($ErrorObject)
    {
        $thisError = [PSCustomObject]@{
    
            Exception = $ErrorObject.Exception
            Message = $ErrorObject.Exception.Message
            FQID = $ErrorObject.FullyQualifiedErrorId
            InovcationInfo = $ErrorObject.InvocationInfo
            ScriptStackTrace = $ErrorObject.ScriptStackTrace
            TargetObject = $ErrorObject.TargetObject
        }
    
        return $thisError
    }
}
PROCESS
{
    try
    {
        Do-SomeNonExistentCommand
    }
    catch
    {
        Write-ErrorDetails -ErrorObject $Error[0]
    }
}
END{}

If saved inside of a file called 123.ps1 and run, your output would look like this:

Exception        : System.Management.Automation.CommandNotFoundException: The term 
                   'Do-SomeNonExistentCommand' is not recognized as the name of a cmdlet, 
                   function, script file, or operable program. Check the spelling of the name, 
                   or if a path was included, verify that the path is correct and try again.
                      at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(
                   FunctionContext funcContext, Exception exception)
                      at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(Int
                   erpretedFrame frame)
                      at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
                   .Run(InterpretedFrame frame)
                      at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction
                   .Run(InterpretedFrame frame)
Message          : The term 'Do-SomeNonExistentCommand' is not recognized as the name of a 
                   cmdlet, function, script file, or operable program. Check the spelling of the 
                   name, or if a path was included, verify that the path is correct and try 
                   again.
FQID             : CommandNotFoundException
InovcationInfo   : System.Management.Automation.InvocationInfo
ScriptStackTrace : at <ScriptBlock><Process>, C:\Users\Pythagoras\desktop\123.ps1: line 22
                   at <ScriptBlock>, <No file>: line 1
TargetObject     : Do-SomeNonExistentCommand

The ScriptStackTrace property might be helpful for troubleshooting, especially if you are writing scripts/tools for an audience and not just your own use. You could add additional functions to do logging with the objects Write-ErrorDetails can provide, etc etc

Upvotes: 2

Related Questions