Can't catch GetWMICOMException

0

Code like this,

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

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

get an error like:

Can't find type [GetWMICOMException]:

catch [COMException] Same

catch [System.Runtime.InteropServices.COMException] just ignored

How can I catch it?

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
powershell
asked on Stack Overflow Jan 30, 2013 by Max D • edited Jul 20, 2018 by Peter Mortensen

4 Answers

1

First. The error is a non-terminating error, so it just notifies. If you want to catch a non-terminating error, use -ErrorAction Stop. Also, I don't think COMException is an exception you can catch. Try this instead:

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"
    }
}
answered on Stack Overflow Jan 30, 2013 by Frode F.
1

You can only catch terminating errors. Add '-ErrorAction Stop' to Get-WmiObject to convert the error to terminating error and try again. On a side note, I would also suggest that you test connectivity to the target system before you run wmi queries against it using a ping request, it can speed up execution especially if you query lots of computers (wmi timeout can slow your script).

try { 
    $NIC = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $Computername -Credential $Credential -filter "IPEnabled = $TRUE" 
}
catch
{
    $_
}
answered on Stack Overflow Jan 30, 2013 by Shay Levy • edited Jan 30, 2013 by Shay Levy
1

I was running into the same issue, and ran across this page. Frode F has the right idea, but I was not satisfied with that answer, so I messed around until I got the behavior that I wanted. I thought I would add a bit in case anyone else runs across this page in the future :

  • As Frode said, you must use -ErrorAction Stop to catch this exception because it is non-terminating
  • You can catch a COMException if you use its fully-qualified name [System.Runtime.InteropServices.COMException]
  • If you want to only catch a COMException when the error record shows GetWMICOMException, as it does when thrown by Get-WMIObject, you can check the error record using an if statement and re-throw the exception if it is not the one you are looking for. Doing so is probably a little excessive in this case because your try block only contains one command. It is doubtful that Get-WMIObject would throw any other kind of COM Exception. However, this might be useful in a case where you had a long pipeline, or multiple commands in the try block.

Simpler version that will catch any 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"
}

More complex version that will only catch a COMException if it is the "GetWMICOMException" thrown by 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"
}
answered on Stack Overflow Mar 19, 2014 by Joel Davies
0

I managed to handle any type of errors in ErrorAction mode "SilentlyContinue" using Try{}Catch and -ErrorVariable:

    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)
    }
answered on Stack Overflow Jul 5, 2014 by Axel Limousin • edited Jul 5, 2014 by Axel Limousin

User contributions licensed under CC BY-SA 3.0