Skip to content

Latest commit

 

History

History
182 lines (152 loc) · 5.04 KB

Tips - Build a custom error info function.md

File metadata and controls

182 lines (152 loc) · 5.04 KB

Build a custom error info function

Often, when in scripts, we must use Try ... Catch statement to grab errors. However, the output displayed is not really friendly.

Let's show this with a sample

Write-Host "Stop On Error Example"
try
{
    Stop-Service -Name FakeService -ErrorAction Stop
}
catch
{
    $_.
    Write-Host "Or another way"
     $_.Exception.Message
}
Stop On Error Example
Stop-Service : Impossible de trouver un service assorti du nom « FakeService ».
Au caractère Ligne:4 : 5
+     Stop-Service -Name FakeService -ErrorAction Stop
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (FakeService:String) [Stop-Service], ServiceCommandException
    + FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.StopServiceCommand
Or another way
Impossible de trouver un service assorti du nom « FakeService ».

The first way is a bid bazaar, and the second is too short.

[Nota] $_ represent the current var in the catch Statement. It's the same thing that $Error[0]

Deep dive in the $error

$error[0] |Select-Object -Property *
PSMessageDetails      :
Exception             : Microsoft.PowerShell.Commands.ServiceCommandException: Impossible de trouver un service assorti du nom «FakeService».
TargetObject          : FakeService
CategoryInfo          : ObjectNotFound: (FakeService:String) [Stop-Service], ServiceCommandException
FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.StopServiceCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : à <ScriptBlock>, <Aucun fichier> : ligne 4
PipelineIterationInfo : {}

$error[0].Exception | Select-Object -Property *
ServiceName    : FakeService
Message        : Impossible de trouver un service assorti du nom « FakeService ».
Data           : {}
InnerException :
TargetSite     :
StackTrace     :
HelpLink       :
Source         :
HResult        : -2146233087

$Error.Exception.Message is an interesting thing

$error[0].CategoryInfo |Select-Object -Property *
Category   : ObjectNotFound
Activity   : Stop-Service
Reason     : ServiceCommandException
TargetName : FakeService
TargetType : String

$Error.CategoryInfo.Reason and $Error.CategoryInfo.Activity too.

$Error[0].InvocationInfo
MyCommand             : Stop-Service
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 4
OffsetInLine          : 5
HistoryId             : 42
ScriptName            :
Line                  :     Stop-Service -Name FakeService -ErrorAction Stop

PositionMessage       : Au caractère Ligne:4 : 5
                        +     Stop-Service -Name FakeService -ErrorAction Stop
                        +     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        : Stop-Service
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :

The property line display useful info, like ScriptLineNumber, ànd OffsetInLine.

Of course, We could put the result of all these properties on a [PSCustomObject] in the catch statement, and display it, but it could be more efficient to build a function to do this (Code reuse is the power :-) )

Build a custom function to display error like we want

First examine the type of $Error

$error | gm
    TypeName : System.Management.Automation.ErrorRecord

Now we can build our function

function Get-Error
{
  param
  (
    [Parameter(ValueFrompipeline)]
    [Management.Automation.ErrorRecord]$ErrorRecord
  )


  process
  {
    $Info = [PSCustomObject]@{
      Exception = $ErrorRecord.Exception.Message
      Reason    = $ErrorRecord.CategoryInfo.Reason
      Target    = $ErrorRecord.CategoryInfo.TargetName
      Script    = $ErrorRecord.InvocationInfo.ScriptName
      Line      = $ErrorRecord.InvocationInfo.ScriptLineNumber
      Column    = $ErrorRecord.InvocationInfo.OffsetInLine
      Date      = Get-Date
      User      = $ENV:UserName
    }
    $Info
  }
}

Question : Why the var is named ErrorRecord and not just Record ? Answer : Error is reserved for the corresponding Automatic Variable.

Function In action

Write-Host "Stop On Error Example"
try
{
    Stop-Service -Name FakeService -ErrorAction Stop
}
catch
{
    $_ | Get-Error
}

Stop On Error Example

Exception : Impossible de trouver un service assorti du nom « FakeService ».
Reason    : ServiceCommandException
Target    : FakeService
Script    :
Line      : 4
Column    : 5
Date      : 13/02/2020 10:52:11
User      : Olivier

this way works fine too.

Write-Host "Stop On Error Example"
try
{
    Stop-Service -Name FakeService -ErrorAction Stop
}
catch
{
    Get-Error -ErrorRecord $_
}

Reference : https://github.com/imseandavis/PowerShell/blob/master/Error%20Handling/Get-ErrorInfo.ps1