Powershell | The Last $Error and Emailing it

OMG some things in Powershell are just too confusing to be useful. What if you need to see the last error message again. What if you want to write it into your script to email you when the error happens?

Well first, its all in $Error

However, $Error is an array.  To access it really requires notation like this:

$Error[0]

The [0] says give me back the last error. Where [1] would say to give me back the second to last error message.

The Problem….

Ok now here is where it gets “funky”. If you just type $Error[0] you get the entire error message like so: (note I am using an error message from some Lync work I have been doing, the names have been changed to protect well me lol)

Set-CsUser : Management object not found for identity “Jerry.Springer@Contoso.com”.
At C:\Scripts\EnableLyncUsers.ps1:138 char:15
+                 Set-CsUser <<<<  -Identity $user.UserPrincipalName -SipAddress $user.UserPrincipalName
    + CategoryInfo          : NotSpecified: (:) [Set-CsUser], ManagementException
    + FullyQualifiedErrorId : Microsoft.Rtc.Management.AD.ManagementException,Microsoft.Rtc.Management.AD.Cmdlets.S
   etOcsUserCmdlet

BUT…. if you type write-host $Error[0] you get this:

Management object not found for identity “Jerry.Springer@Contoso.com”.

So what gives right??? Why when you use Write-Host OR even better when you try to email $Error[0] do we get the crappy short error message? Well I don’t have the answer BUT I do have a great work around.

The Solution….

[string]$ErrorString = $Error[0].Exception
[string]$ErrorString = $ErrorString + ” `n `n ”
[string]$ErrorString = $ErrorString + $Error[0].InvocationInfo.PositionMessage

(that’s 3 lines BTW)

As far as I can tell the only thing one needs are the short error message and the line, script, and command. To do this use the code above and then simply use Write-Host or email that new $ErrorString variable. If you need other data follow the info below from how I figured this out.

Emailing the Error? Simply use this code (replace stuff inside of < > then remove the < >):

    [string]$ErrorString = $Error[0].Exception
    [string]$ErrorString = $ErrorString + ” `n `n ”
    [string]$ErrorString = $ErrorString + $Error[0].InvocationInfo.PositionMessage

    $SmtpClient = new-object system.net.mail.smtpClient
    $MailMessage = New-Object system.net.mail.mailmessage
    $SmtpClient.Host = “<SMTP IP OR NAME>”
    $mailmessage.from = <from@domain.com>
    $mailmessage.To.add(“email1@domain.com,email2@domain.com”)
    $mailmessage.Subject = “<Subject of Email>”
    $MailMessage.IsBodyHtml = $false
    $mailmessage.Body = $ErrorString
 
    $smtpclient.Send($mailmessage)

How did I figure this out?

First I indexed $Error to get me the first result [0]

Next I used the power of Get-Member

$Error[0] | Get-Member

This dumped out all the properties

TypeName: System.Management.Automation.ErrorRecord

Name                  MemberType     Definition                                                                    
—-                  ———-     ———-                                                                    
Equals                Method         bool Equals(System.Object obj)                                                
GetHashCode           Method         int GetHashCode()                                                             
GetObjectData         Method         System.Void GetObjectData(System.Runtime.Serialization.SerializationInfo inf…
GetType               Method         type GetType()                                                                
ToString              Method         string ToString()                                                             
CategoryInfo          Property       System.Management.Automation.ErrorCategoryInfo CategoryInfo {get;}            
ErrorDetails          Property       System.Management.Automation.ErrorDetails ErrorDetails {get;set;}             
Exception             Property       System.Exception Exception {get;}                                             
FullyQualifiedErrorId Property       System.String FullyQualifiedErrorId {get;}                                    
InvocationInfo        Property       System.Management.Automation.InvocationInfo InvocationInfo {get;}             
PipelineIterationInfo Property       System.Collections.ObjectModel.ReadOnlyCollection`1[[System.Int32, mscorlib,…
TargetObject          Property       System.Object TargetObject {get;}                                             
PSMessageDetails      ScriptProperty System.Object PSMessageDetails {get=& { Set-StrictMode -Version 1; $this.Exc…

All of the properties normally can be accessed like this:

$Error[0].Exception

But if you try to write-host $Error[0].InvocationInfo you get:

System.Management.Automation.InvocationInfo

Well that’s not very useful… the reason for this is there are deeper items in the $Error[0].InvocationInfo tree. So if we go ahead and whip out get-member again on $Error[0].InvocationInfo lets see what we get:

TypeName: System.Management.Automation.InvocationInfo

Name             MemberType Definition                                                                             
—-             ———- ———-                                                                             
Equals           Method     bool Equals(System.Object obj)                                                         
GetHashCode      Method     int GetHashCode()                                                                      
GetType          Method     type GetType()                                                                         
ToString         Method     string ToString()                                                                      
BoundParameters  Property   System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=2.0.0.0, Cu…
CommandOrigin    Property   System.Management.Automation.CommandOrigin CommandOrigin {get;}                        
ExpectingInput   Property   System.Boolean ExpectingInput {get;}                                                   
HistoryId        Property   System.Int64 HistoryId {get;}                                                          
InvocationName   Property   System.String InvocationName {get;}                                                    
Line             Property   System.String Line {get;}                                                              
MyCommand        Property   System.Management.Automation.CommandInfo MyCommand {get;}                              
OffsetInLine     Property   System.Int32 OffsetInLine {get;}                                                       
PipelineLength   Property   System.Int32 PipelineLength {get;}                                                     
PipelinePosition Property   System.Int32 PipelinePosition {get;}                                                   
PositionMessage  Property   System.String PositionMessage {get;}                                                   
ScriptLineNumber Property   System.Int32 ScriptLineNumber {get;}                                                   
ScriptName       Property   System.String ScriptName {get;}                                                        
UnboundArguments Property   System.Collections.Generic.List`1[[System.Object, mscorlib, Version=2.0.0.0, Culture=…

Ah… there’s more stuff. Lastly I just needed to figure out what items inside of $Error[0].InvocationInfo I needed. Turns out just one thing. So to write-host it all I needed to do is call:

Write-Host $Error[0].InvocationInfo.PositionMessage

Hope that opens your mind to how more complex objects work in Powershell.

Hey!

Did I help? Make Sense? Something Wrong? Put it in the comments. Love to hear when my write-ups help folks out.

Enjoy

-Eric

Advertisements

Tags: , ,

About Eric

My name is Eric Weintraub. I am an IT Professional with over 12 years of real world experience. I currently work as a Senior IT Manager for a large software company that develops products for Information Technology workers. Professionally, I love what I do and it shows in my work. Personally, I enjoy technology as a whole. Enterprise Technology, Social Media, and Mobile technologies are all things I follow. I also love to play golf, go snowboarding, cook, love to eat, and read. Also big on photography, check out my recent photography at http://www.ericweintraubphotography.com and also Flickr: http://www.flickr.com/photos/ericweintraub/. As much as I don’t have a lot of free time, I always come across things that I believe could help others. I just wanted to be able to share what I find with others. Thanks for reading the blog, please setup a RSS feed and keep in touch! Eric Weintraub

One response to “Powershell | The Last $Error and Emailing it”

  1. rjasonmorgan says :

    All you need to do is $error[0].exception.message the exception property contains a nested object, you’re looking to access the message property of the exception object.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: