Powershell $ Error对象不会立即填充PSM1模块内部

时间:2012-07-11 21:49:23

标签: powershell exception-handling

我遇到了Powershell的一个特殊问题。我在catch块中捕获了一个Exception,但是没有填充全局$ Error对象。

一个简单的例子,其表现如预期的那样:

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)"  
  }
}

如果您致电Bar

,则输出正如您所期望的那样
Caught an error - current error count 1
Cleaning up - current error count 1

我遇到问题的代码几乎完全相同,只是它从模块加载Foo。不确定这是一个bug,还是我不理解的东西(必须检查我的Powershell in Action书!)

如果我将Foo保存到模块 - 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

然后我执行以下

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

我最终得到了

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

请注意,Foo不再看到对$ Error所做的任何更改。因此代码的模块化正在改变错误传播行为。任何人都可以为这背后的推理而感到高兴吗?

我应该注意,我可以通过自动变量$ _来获取特定捕获的异常,但我希望在调用堆栈中此时保持整个集合。

2 个答案:

答案 0 :(得分:10)

正如Ethan所提到的,你需要查看$ global:error来查看所有错误。模块总是有自己的$ error变量,但(大部分)没有使用它。

背景:有一次,我们考虑将模块代码中发生的错误隔离到模块范围,但最终决定将所有错误添加到全局错误集合中,因为它本质上是一个错误日志(如内存中的事件日志) 。)不幸的是,在发布之前没有删除模块作用域$ error,所以你需要使用全局作用域限定符来访问“真正的”$ error变量。

微软公司的Bruce Payette

答案 1 :(得分:8)

之前我没有注意到,但也许$ error集合的范围与任何其他变量一样。尝试比较测试脚本中关键点的以下两个显式范围变量的值:

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

让我知道你是怎么过的。