无法捕获GetWMICOMException

时间:2013-01-30 08:24:02

标签: powershell

这样的代码,

try { $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -filter "IPEnabled = $TRUE" }

catch [GetWMICOMException]
{
    "Error 1"
}
catch [System.UnauthorizedAccessException]
{
    "Error 2"
}

得到如下错误:

  

找不到类型[GetWMICOMException]:

     

catch [COMException]相同

     

catch [System.Runtime.InteropServices.COMException]刚被忽略

我怎样才能抓住它?

Get-WmiObject : RPC server was unavailable. (Exception HRESULT: 0x800706BA)
F:\PowerShell Scripts\Project1.NetReconfigurer\proj1.ps1:36 :33
+             $NIC = Get-WmiObject <<<<  Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -filter "IPEnabled = $TRUE"

+ CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

4 个答案:

答案 0 :(得分:1)

首先。该错误是一个非终止错误,因此它只是通知。如果要捕获非终止错误,请使用-ErrorAction Stop。另外,我不认为COMException是一个你可以捕获的例外。试试这个:

try { $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -filter "IPEnabled = $TRUE -ErrorAction Stop}
catch [System.UnauthorizedAccessException]
{
    "Error 2"
}
catch [Exception]
{
    if ($_.Exception.GetType().Name -eq "COMException") {
        "Error 1"
    }
}

答案 1 :(得分:1)

您只能捕获终止错误。将“-ErrorAction Stop”添加到Get-WmiObject以将错误转换为终止错误,然后重试。另外,我还建议您在使用ping请求对它运行wmi查询之前测试与目标系统的连接,它可以加快执行速度,尤其是在查询大量计算机时(wmi超时会降低脚本速度)。

try { 
    $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -filter "IPEnabled = $TRUE" 
}
catch
{
    $_
}

答案 2 :(得分:1)

我遇到了同样的问题,并跑过这个页面。 Frode F有正确的想法,但我对这个答案并不满意,所以我搞砸了,直到我得到了我想要的行为。我想我会添加一些,以防将来有人遇到这个页面:

  • 正如Frode所说,你必须使用-ErrorAction Stop来捕获这个异常,因为它是非终止的
  • 如果使用其完全限定名称,则可以捕获COMException [System.Runtime.InteropServices.COMException]
  • 如果您只想在错误记录显示GetWMICOMException时捕获COMException,就像Get-WMIObject抛出时一样,您可以使用if语句检查错误记录,如果不是,则重新抛出异常你在找。在这种情况下,这样做可能有点过分,因为您的try块只包含一个命令。令人怀疑的是,Get-WMIObject会抛出任何其他类型的COM异常。但是,如果您有一个长管道或try块中有多个命令,这可能很有用。

将捕获任何COMException的更简单版本:

try { $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -Filter "IPEnabled = $TRUE" -ErrorAction Stop}

catch [System.Runtime.InteropServices.COMException]
{
    "Error 1"
}
catch [System.UnauthorizedAccessException]
{
    "Error 2"
}

更复杂的版本,如果它是&#34; GetWMICOMException&#34;将只捕获COMException; Get-WMIObject抛出:

try { $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -Filter "IPEnabled = $TRUE" -ErrorAction Stop}

catch [System.Runtime.InteropServices.COMException]
{
    if ($_.FullyQualifiedErrorId.StartsWith("GetWMICOMException")
    {
        "Error 1"
    }
    else { throw }
}
catch [System.UnauthorizedAccessException]
{
    "Error 2"
}

答案 3 :(得分:0)

我设法使用Try {} Catch和-ErrorVariable处理ErrorAction模式“SilentlyContinue”中的任何类型的错误:

    foreach ($Server in $Server_List)
    {
        $ErrorVar = $null
        $Server_Model = $null

        try
        {
            $Server_Info= Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Server -Credential $Credential -ErrorAction SilentlyContinue -ErrorVariable ErrorVar | Select Model
        }
        catch [System.UnauthorizedAccessException] # here $ErrorVar.Exception doesn't exist but $ErrorVar.ErrorRecord.Exception
        {
            $Msg = "Powershell cmdlet on $Server : DCOM unauthorized access"
            $Msg | Write-Warning
        }

        if ($ErrorVar.Exception)
        {
            switch ($ErrorVar)
            {
                { $_.Exception.GetType().Name -eq "COMException" }
                {
                    $Msg = "Powershell cmdlet on $Server : RPC server is unavailable"
                    $Msg | Write-Warning

                    break
                }
                { $_.Exception.GetType().Name -eq "ManagementException" }
                {
                    $Msg = "Powershell cmdlet on $Server : user credentials cannot be used for local connections.`nRetrying without credential."
                    $Msg | Write-Warning
                    $Server_Info = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Server | Select Model # when the script is hosted on a computer within the Server_List

                    break
                }
                default
                {
                    $Msg = "Powershell cmdlet on $Server : unexpected error"
                    $Msg | Write-Warning
                }
            }
        }

        if ($Server_Info)
        {
                $Server_Info_Pso =  New-Object PSObject -Property @{
                    HostName = $Server
                    Model = $Server_Info.Model
                }
        }
        else
        {           
            $Server_Info_Pso =  New-Object PSObject -Property @{
                HostName = $Server
                Model = 'Unavailable'
            }
        }

        $Server_Info_PsoCol = $Server_Info_PsoCol + @($Server_Info_Pso)
    }