英文:
How to stop casting error from populating `$Error` in 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
这将打印如下内容(False
只是调用的返回值):
False
Cannot convert value "\.\root\ccm\clientsdk:CCM_ClientUtilities" to type "System.Management.ManagementClass". Error: "Invalid parameter "
At C:\_\t.ps1:26 char:89
+ … re'; return ([wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities') } …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastToWMIClass
我不想让这种情况发生。我希望能完全控制错误处理,因为错误本身也是函数逻辑的一部分(因为它表示未来肯定不会有重启任务)。我希望能像在使用cmdlet时使用-ErrorAction ignore
一样控制它。
我尝试使用以下方法:
$ErrorActionPreference = 'ignore'
$util = [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities'
甚至以下方法(是的,有点疯狂):
$ErrorActionPreference = 'ignore'
$util = Invoke-Command -ScriptBlock { $ErrorActionPreference = 'ignore'; return ([wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities') } -ea Ignore
但都没有起作用...
我开始怀疑,这是否可能?
请注意:这段代码只是一个示例,我的问题是,一般情况下,如何阻止强制类型转换错误进入$Error
?
英文:
i have the following code:
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
}
which is part of a function that, as you can see, checks if a system reboot is pending.
That casting to [wmiclass]
is possible only when a reboot is pending.
The function works correctly, but with the side effect of the casting error (when a reboot is not pending) going into the $Error
automatic variable. You can check with:
$error.clear()
Test-PendingReboot
$error
This will print the following (False
is just the return value of the call):
False
Cannot convert value "\.\root\ccm\clientsdk:CCM_ClientUtilities" to type "System.Management.ManagementClass". Error: "Invalid parameter "
At C:\_\t.ps1:26 char:89
+ … re'; return ([wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities') } …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvalidCastToWMIClass
I don't want that.
I want to have complete control over the error, as the error itself is also part of the logic of the function (because it means that a reboot is certainly not pending).
I want to control it as when using -ErrorAction ignore
instead of silentlycontinue
with a cmdlet.
I tried using the following:
$ErrorActionPreference = 'ignore'
$util = [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities'
or even the following (yes that's mad):
$ErrorActionPreference = 'ignore'
$util = Invoke-Command -ScriptBlock { $ErrorActionPreference = 'ignore'; return ([wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities') } -ea Ignore
but nothing works...
I'm starting to doubt, Is it even possible?
PLEASE NOTE: this piece of code is just an example, my question is, in general, how to stop casting error from getting into $Error
?
thanks
答案1
得分: 1
function Test-PendingReboot {
$util = & { [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' } 2>&1
$util.ForEach{
if ($_ -is [System.Management.Automation.ErrorRecord]) {
"Your error: $_"
}
else {
$status = $_.DetermineIfRebootPending()
if ($null -ne $status) { $status.RebootPending }
}
}
}
要完全拦截错误,您可以考虑启动一个昂贵且繁琐的新PowerShell会话:
$Result = PowerShell {
$util = & { [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' } 2>&1
$util.ForEach{
if ($_ -is [System.Management.Automation.ErrorRecord]) {
"Your error: $_"
}
else {
$status = $_.DetermineIfRebootPending()
if ($null -ne $status) { $status.RebootPending }
}
}
}
英文:
You might consider to redirect the (error) stream:
function Test-PendingReboot {
$util = & { [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' } *>&1
$util.ForEach{
if ($_ -is [System.Management.Automation.ErrorRecord]) {
"Your error: $_"
}
else {
$status = $_.DetermineIfRebootPending()
if ($null -ne $status) { $status.RebootPending }
}
}
}
To completely intercept the error, you might consider to start an expensive and cumbersome new PowerShell session:
$Result = PowerShell {
$util = & { [wmiclass]'\.\root\ccm\clientsdk:CCM_ClientUtilities' } *>&1
$util.ForEach{
if ($_ -is [System.Management.Automation.ErrorRecord]) {
"Your error: $_"
}
else {
$status = $_.DetermineIfRebootPending()
if ($null -ne $status) { $status.RebootPending }
}
}
}
答案2
得分: 0
这个从不例外,只要安装了 SCCM 客户端 (get-package 'configuration manager client'):
# 或者使用 Invoke-WmiMethod
$myargs = @{ namespace = 'root\ccm\clientsdk'
class = 'CCM_ClientUtilities'
name = 'DetermineIfRebootPending' }
Invoke-CimMethod @myargs | select RebootPending
RebootPending
-------------
False
英文:
This never has an exception as long as sccm client is installed (get-package 'configuration manager client'):
# or Invoke-WmiMethod
$myargs = @{ namespace = 'root\ccm\clientsdk'
class = 'CCM_ClientUtilities'
name = 'DetermineIfRebootPending' }
Invoke-CimMethod @myargs | select RebootPending
RebootPending
-------------
False
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论