错误的PowerShell cmdlet填充了$Error自动变量

utugiqy6  于 2023-03-02  发布在  Shell
关注(0)|答案(2)|浏览(143)

为了在远程计算机上运行的PowerShell启动/登录脚本出现错误时得到通知,我倾向于使用以下内容结束脚本:

If ($Error) {
    (Code that sends a notification email to system administrators attaching the contents of the $Error variable for troubleshooting)
}

这是一个很好的"讲述故事"来收集边缘案例/错误。但是,我发现一些基本的内置PowerShell cmdlet即使在成功运行时也会将数据转储到$Error中-例如,尝试:

$Error.Clear()
Get-NetIPConfiguration
$Error

您将在$Error中看到一系列错误,这些错误在正常输出期间不会显示,但看起来如下所示:
获取网络路由:CIM查询在CIM服务器上的ROOT/StandardCimv2/MSFT_NetRoute类别的示例时没有找到匹配的MSFT_NetRoute对象:SELECT * FROM MSFT_NetRoute WHERE((目的地前缀类似于"0.0.0.0/0"))AND((接口别名类似于"OpenVPN Wintun"))。请验证查询参数并重试。
获取网络连接配置文件:找不到属性"InterfaceAlias"等于"Local Area Connection"的MSFT_NetConnectionProfile对象。请验证该属性的值并
再试。

$Error.Clear()
Get-NetIPAddress
$Error

将返回:
“无限:术语"Infinite"无法识别为cmdlet、函数、脚本文件或可操作程序的名称。请检查名称的拼写;如果包含路径,请验证路径是否正确,然后重试。
(毫无疑问,这是微软需要在某个时候解决的一个不错的小bug!)
由于不太可能在短期内修复这些cmdlet,是否有一种方法可以运行这些cmdlet,而不会让它们的无用信息堵塞$Error?
不是Powershell: How can I stop errors from being displayed in a script?的副本,因为它涵盖了在cmdlet "失败"运行期间 * 在PowerShell控制台上实际显示为红色 * 的错误;这是关于在表面上"成功"运行小命令期间由一些小命令在后台生成的错误,由于某些原因 * 仅被写入自动$Error变量 *。
尽管如此,我已经尝试了该帖子中建议的一些解决方案:

  • 使用-ErrorAction Ignore运行cmdlet
  • 使用-ErrorAction静默运行cmdlet继续
  • 在try {} catch {}内运行cmdlet
  • 使用-ErrorAction Stop在try {} catch {}内运行cmdlet
  • 运行后面带有2〉$null的cmdlet
  • 在运行cmdlet之前设置$ErrorActionPreference ="SilentlyContinue

我可能在问不可能的问题,但是这些cmdlet的行为方式确实使$Error很难用作实际的日志,我只是想知道我是否错过了一个技巧。
我希望能够以这样一种方式封装有缺陷的cmdlet,即"隐藏"错误不会进入自动$Error变量。

dwthyt8l

dwthyt8l1#

我同意@zett42的评论:* 我认为您无法真正阻止cmdlet添加到$Error*。
还要知道这些“幻像错误”可能已经在使用简单的(Try/Catch)语句时发生,例如:

Try { 1/0 } Catch {}

无论如何,您可能会考虑标记最后一个,并删除添加在其后的错误/类似:

$HashCode = if ($Error) { $Error[0].GetHashCode() }
Get-NetIPAddress
While($Error -and $Error[0].GetHashCode() -ne $HashCode) { $Error.RemoveAt(0) }
mi7gmzs6

mi7gmzs62#

使用公共-ErrorVariable参数,以便仅收集cmdlet * 直接 * 发出或 * 有意传递 * 的(非终止)错误(将不捕获它在内部静音或忽略的错误):

# $errs is a self-chosen variable; note that it must be specified WITHOUT $
Get-NetIPAddress -ErrorVariable errs

# $errs now contains any (non-terminating) errors emitted by the 
# Get-NetIPAddress call, as a [System.Collections.ArrayList] instance.
# (If no errors occurred, the list is empty).

注:要同时 * 静音 * 错误,请将-ErrorVariable errs-ErrorAction SilentlyContinue结合使用(-ErrorAction SilentlyContinue * 不 * 工作-见下文)。
自动变量$Error旨在提供所有错误的 * 会话范围 * 日志。
然而,故意 * 忽略 * 错误的(脚本)cmdlet可以通过在内部调用中使用-ErrorAction Ignore来避免记录不必要的错误-假设错误不仅要被 * 静音 *,而且不需要被 * 检查 *。
(If在使用-ErrorVariable收集错误之后,需要检查错误,使用-ErrorAction Ignore * 不是 * 选项,因为它阻止错误收集。)
不幸的是,NetTCPIP模块中基于CDXML的cmdlet(如Get-NetIPAddress)在-ErrorAction Ignore足够的情况下使用-ErrorAction SilentlyContinue

  • 可以想象 *,cmdlet生成代码早于PowerShell v3,当时引入了Ignore值。

相关问题