Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell $Error object not immediately populating inside PSM1 module

I'm encountering a peculiar issue with Powershell. I'm catching an Exception in a catch block, but the global $Error object is not being populated.

A trivial example, where this would behave as expected is this:

function Bar
{
  Foo
}

function Foo
{
  try
  {
    $Error.Clear()
    throw "Error!"
  }
  catch
  {
    "Caught an error - current error count $($Error.Count)"  
  } 
  finally
  {
    "Cleaning up - current error count $($Error.Count)"  
  }
}

Output is as you would expect if you call Bar

Caught an error - current error count 1
Cleaning up - current error count 1

The code I'm having trouble with is nearly identical, except that it loads Foo from a module. Not sure if this is a bug, or simply something I don't understand (will have to check my Powershell in Action book!)

If I save Foo off to a module - Foo.psm1

function Foo
{
  try
  {
    $Error.Clear()
    throw "Error!"
  }
  catch
  {
    "Caught an error - current error count $($Error.Count)"  
  } 
  finally
  {
    "Cleaning up - current error count $($Error.Count)"  
  }
}

Export-ModuleMember -Function Foo

Then I perform the following

Import-Module .\Foo.psm1
$Error.Clear()
"Current error count $($Error.Count)"
Foo
"Current error count $($Error.Count)"

I end up with

Current error count 0
Caught an error - current error count 0
Cleaning up - current error count 0
Current error count 1

Notice that Foo no longer sees any changes made to $Error. So the module-ification of the code is changing error propagation behavior. Can anyone chime in with the reasoning behind this?

I should note that I can get at the specific caught exception via the automatic variable $_, but I'm looking to get a hold of the entire collection at this point in the call stack.

like image 623
Ethan J. Brown Avatar asked Jul 11 '12 21:07

Ethan J. Brown


2 Answers

I hadn't noticed that before, but perhaps the $error collection is scoped to the module like any other variables. Try comparing the values of the following two explicitly scoped variables at key points in your test script:

"Errors - Global: {0}; Module: {1}" -f $global:error.count, $script:error.count

Let me know how you get on.

like image 168
x0n Avatar answered Oct 26 '22 03:10

x0n


As Ethan mentioned, you need to look at $global:error to see all of the errors. Modules always have they're own $error variable but it's (mostly) not used.

background: at one point, we had considered isolating errors that occurred in module code to the module scope but ultimately decided to add all errors to the global error collection since it is essentially a log of errors (like an in-memory eventlog.) Unfortunately the module scoped $error wasn't removed before the release and so you need to use the global scope qualifier to access the "real" $error variable.

Bruce Payette, Microsoft Corporation

like image 34
Bruce Payette Avatar answered Oct 26 '22 02:10

Bruce Payette