如何阻止PowerShell中的强制转换错误填充$Error自动变量?
问题描述
我写了一个检查系统是否有待重启任务的PowerShell函数:
function Test-PendingReboot { try { $util = [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' $status = $util.DetermineIfRebootPending() if (($null -ne $status) -and $status.RebootPending) { return $true } } catch {} return $false }
这个函数逻辑正常,但当系统无需重启时,[wmiclass]的强制转换错误会被写入$Error自动变量。执行以下代码可以复现这个问题:
$error.clear() Test-PendingReboot $error
返回结果里会包含强制转换的错误信息。我希望完全控制这个错误,把它当作无需重启的判断依据,而且不让它写入$Error,就像使用cmdlet的-ErrorAction Ignore参数那样。我试过设置$ErrorActionPreference = 'Ignore',甚至用Invoke-Command嵌套设置,但都没用。
我的核心问题是:如何在PowerShell中阻止强制转换错误进入$Error自动变量?
解决方案
PowerShell里,[wmiclass]这种直接类型转换的错误属于终止错误,但默认try/catch在非严格模式下抓不住这类错误,而且$ErrorActionPreference对类型转换操作根本不生效。要解决这个问题,最直接的办法是改用支持-ErrorAction参数的cmdlet来替代类型转换,比如Get-CimInstance或者Get-WmiObject。
推荐修改方案
function Test-PendingReboot { # 用Get-CimInstance获取实例,-ErrorAction Ignore直接忽略错误,不写入$Error $util = Get-CimInstance -Namespace root\ccm\clientsdk -ClassName CCM_ClientUtilities -ErrorAction Ignore if ($null -ne $util) { $status = $util.DetermineIfRebootPending() if ($status.RebootPending) { return $true } } return $false }
这个写法的好处是:
- 通过
-ErrorAction Ignore直接屏蔽获取实例失败的错误,完全不会写入$Error - 逻辑和原函数一致:能获取到实例就检查重启状态,获取不到就直接返回
false
保留类型转换的替代方案
如果一定要保留[wmiclass]的写法,可以先检查目标类是否存在,避免触发转换错误:
function Test-PendingReboot { try { # 先检查类是否存在,-ErrorAction Ignore屏蔽检查错误 $classExists = Get-CimClass -Namespace root\ccm\clientsdk -ClassName CCM_ClientUtilities -ErrorAction Ignore if ($classExists) { $util = [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' $status = $util.DetermineIfRebootPending() if ($status.RebootPending) { return $true } } } catch {} return $false }
这种方式先通过Get-CimClass验证类存在后再做类型转换,从根源上避免了转换错误,自然不会有错误写入$Error。
内容的提问来源于stack exchange,提问作者aetonsi
相关产品推荐
相关产品推荐

