PowerShell Quick Tip: Process your errors more efficiently with Group-Object

Instead of going through your errors one at a time, since there are often cases where the same error is repeated multiple times, use Group-Object with $error to filter out the duplicates so that you can see what the real errors are that you need to deal with.  For example, right now I have 256 errors stored in my $error variable.  To figure out what I need to really look at, I can invoke this command:When working with large script files or modules, you may encounter situations where you have a large number of errors that you need to deal with.  This can be overwhelming, especially when you have looping constructs in your scripts that cause the errors to be raised over and over again.  When you are facing hundreds of errors output from a script, how do you process them all?  Fortunately there is a quick an easy way to make sense of your errors and identify what really needs to be fixed.

All errors are recorded by default in the $error variable.  This variable allows you to access any errors you have received in PowerShell, to a maximum count as identified by the $MaximumErrorCount variable.  By default this is set to 256, and dealing with 256 errors can be impossible without the proper divide and conquer strategy.  Also, the $error variable even includes errors that were hidden by trap, catch, or error action preferences, so this variable is very useful when troubleshooting all errors you have in your scripts.  As mentioned though, this can be a lot of information to digest, so it is important to know how to process it efficiently.

Instead of going through your errors one at a time, since there are often cases where the same error is repeated multiple times, use Group-Object with $error to filter out the duplicates so that you can see what the real errors are that you need to deal with.  For example, right now I have 256 errors stored in my $error variable.  To figure out what I need to really look at, I can invoke this command:

$error | Group-Object | Format-Table Count,Name -AutoSize

That gives me the following results:

Count Name
----- ----
1 Exception calling "ShowDialog" with "0" argument(s): "Property 'PS...
2 Property 'PSiscontainer' cannot be found on this object. Make sure...
240 Property 'Extension' cannot be found on this object. Make sure tha...
13 Property 'Name' cannot be found on this object. Make sure that it ...

This short list of four errors is much less intimidating than a huge list of 250 errors.  Once you have the short list, it becomes much easier to figure out where to get started.  You can also go further by expanding on these details like this:

$Error | Group-Object | Format-List Count,@{Name='Error';Expression={$_.Name}},@{Name='Location';Expression={$_.Group[0].InvocationInfo.PositionMessage}}

A command like that will yield results that look something like the following:

Count    : 1
Error    : Exception calling "ShowDialog" with "0" argument(s): "Property '
PSiscontainer' cannot be found on this object. Make sure that it
exists."
Location :
At C:\Users\kmunro\Documents\WindowsPowerShell\Modules\Add-on.Te
st\Add-on.Test.psm1:860 char:20
+         $Form1.ShowDialog <<<< ()
Count    : 2
Error    : Property 'PSiscontainer' cannot be found on this object. Make su
re that it exists.
Location :
At C:\Users\kmunro\Documents\WindowsPowerShell\Modules\Add-on.Te
st\Add-on.Test.psm1:1236 char:16
+                         if ($obj. <<<< PSiscontainer) {
Count    : 240
Error    : Property 'Extension' cannot be found on this object. Make sure t
hat it exists.
Location :
At line:1 char:11
+ if ($this. <<<< Extension.Length -gt 0){$this.Name.Remove($thi
s.Name.Length - $this.Extension.Length)}else{$this.Name}
Count    : 13
Error    : Property 'Name' cannot be found on this object. Make sure that i
t exists.
Location :
At line:1 char:7
+ $this. <<<< Name

That’s much better.  Now I can see which errors are happening most frequently and concentrate my efforts on them while knowing I only have a few unique errors to deal with.

I hope this helps you work out errors in your own scripts and modules.

Kirk out.

P.S. Wouldn’t it be cool if there was a PowerGUI Script Editor Add-on that showed you the contents of the $error variable, grouped like this, with the ability to double-click and go to the appropriate position in the appropriate file…could make a great entry for the PowerGUI Challenge contest that is going on right now!

Advertisements

2 thoughts on “PowerShell Quick Tip: Process your errors more efficiently with Group-Object

  1. Kirk,

    Great example – and solution for shortening the debug timeline – thanks!
    =
    As an aside in your example above,

    I’m seeing something that illustrates a frustration and that is in the PowerShell environment itself for presenting the content of an object to the PowerShell console.

    While I can decide to route the data to a CSV or HTML file and be presented the data using these other software tools, this doesn’t address the core situation.

    The reason I also bring this question up is because depending on the server where PowerShell is installed, most typical environment settings aren’t something one wants to tweak (such as setting the console width, height or character type and point size – of a PowerShell session) only circumventing the core issue at hand.

    Some PowerShell default environment setting is telling PowerShell to present the content of objects in one of two ways (depending at how one arrives at the output) for the Format-List, Format-Table, in the Select-object and Get-ChildItem cmdlets as well.

    [1] PowerShell has decided (for me) to either provide elipse characters (…) to imply there is more content, but PowerShell isn’t going to provide the rest using this format.

    or

    [2] PowerShell decides to wrap the content of the value of the data onto the next line after each 79th value of a row of data, instead of continuing to present the data on the same line (on out to the right side 80th, 81st … as wide as needed), which in turn one needs to use the horizontal tile and slide-right to view this data output.

    One intermediate help you had showed me is to invoke the enviroment setting –

    $FormatEnumerationLimit = 1000

    which does help some by allowing Format-Table to present more than four columns of data, but doesn’t completely clean up the situation.

    =

    One true way of showing this phenomena is to use the Get-Content {filename} cmdlet on a file that has rows of data over 80 columns wide.

    The result is that PowerShell will decide on its own to crop the content at the 79th column, insert a carriage-return/line-feed and continue presenting the 80th value of each row onto another line – until the 79th column.

    At that point, the cycle continues itself.

    Using CMD.EXE, I can type the content of a file to the console, then invoke PowerShell and use the Get-Content on the same file where PowerShell has made the decision to present output, in no wider than 79 (or 80) columns.

    What is PowerShell deciding for me and what approaches will it take to work around these situations?

    Thanks and best regards,
    -dpc-

    Like

    1. Hi David,

      Good question, and I’ll try to clarify a few things to help you out with this.

      First, $FormatEnumerationLimit only affects enumerable items when displaying their contents in PowerShell output. It has nothing to do with the number of columns shown in a table. For example, if you look at the results of a simple call to Get-PSProvider, the number of drives you see in the Drives column in the table are directly affected by the number assigned to $FormatEnumerationLimit.

      Next, regarding PowerShell deciding to use ellipsis characters, that is done by default by the table formatter. If you don’t want ellipsis characters, you should use -Autosize.

      Last, with respect to your question about Get-Content, Get-Content retrieves the contents of a text file and returns one string for each item in the text file. You can see this by calling Get-Content filename.txt | Measure-Object. That will show a count representing the number of lines in the file. If the lines in the file exceed the buffer width in your PowerShell console, you will see those lines wrapped without ellipses. You can get a preview of the file contents without wrapping using a pretty neat trick with ForEach-Object. For example, to see the contents of any file without exceeding the current buffer width, and to automatically place an ellipsis where appropriate (yes, you can even add them yourself!), you could execute this command:

      Get-Content filename.txt | ForEach-Object {
      if ($_.Length -gt $host.UI.RawUI.BufferSize.Width) {
      (-join $_[0..($host.UI.RawUI.BufferSize.Width – 5)]) + ‘…’
      } else {
      $_
      }
      }

      That would give you a way to preview a file that contains many long strings without having to deal with buffer overload in your PowerShell console.

      Kirk out.

      Like

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