Search code examples
powershellwmicim

CIM vs WMI returning different information


I was trying to take advantage of CIM's built-in parallel processing to get information about all the installed printers against a given subnet of computers. The script works faster than my WMI variation, but doesn't return the same information and doesn't always return as much as the Get-WmiObject call.

EDIT: The information the script drops is information about entire computers.

Here's the CIM version:

$Computer = Get-Content -Path c:\Scripts\input.txt  

$Objects = foreach ($ComputerName in $Computer) {
    # New CIM Instance 
    Write-Host Collecting information on $ComputerName 
    $Cim = New-CimSession -ComputerName $ComputerName 

    # Collect Printer Info
    Get-CimInstance -CimSession $Cim -Class Win32_printer -Property deviceid, drivername, portname, systemName

    # Define Hashtable properties 
    $ObjectProperties = @{
        SystemName = $Cim.systemName
        DeviceID   = $Cim.deviceid
        DriverName = $Cim.drivername
        PortName   = $Cim.portname
    }

    # Create new object
    New-Object PSObject -Property $ObjectProperties        
}

# Export Results 
$Objects | Select DeviceID, DriverName, PortName, SystemName |
    Export-Csv - NoTypeInformation -Path c:\Scripts\output.csv

Here's the WMI version:

$results = @()
$Computer = Get-Content -Path c:\Scripts\input.txt

# Check each computer in the list 
foreach ($ComputerName in $Computer) {
    $results += Get-WmiObject -Class Win32_printer -cn $ComputerName |
                Select deviceid, drivername, portname, systemName
    Start-Sleep -Milliseconds 500
}

# Export to CSV file
$Results | Select DeviceID, DriverName, PortName, SystemName |
    Export-Csv -NoTypeInformation -Path c:\Scripts\output.csv

We sometimes need to run this script against multiple subnets. I moved to the CIM sessions because it reduced the total run of the script to consistently under 5 minutes, but if it's not going to return all of the information, it might be better to wait.

Does anyone have any idea on how to prevent CIM from dropping information?

It should be noted that WinRM is not enabled by default on these machines and the script has to force enable CIMs with the following command.

& "c:\Scripts\SnIPT\psexec.exe" \\$ComputerName -s -d -n 5 winrm.cmd quickconfig -q -force

Solution

  • The same WMI-class should return the same data (however CIM-cmdlets convert dates ++). Since you haven't explained what's different I'd guess it's missing output for certain computers. Usually this is because the target computer is missing Windows Management Framework 3.0 or later (think PS 3.0+) which is required for CIM. If that's the case, it should generate an error that you can catch and use to use DCOM (same as WMI) as a fallback. Ex:

    $Computer = Get-Content -Path c:\Scripts\input.txt  
    
    $DCOM = New-CimSessionOption -Protocol Dcom    
    
    $Objects = ForEach($ComputerName in $Computer)
    {
        #New Cim Instance with fallback to DCOM 
        Write-Host Collecting information on $ComputerName 
    
        $Cim = $null
        try {
            $Cim = New-CimSession -ComputerName $ComputerName -ErrorAction Stop
        } catch [Microsoft.Management.Infrastructure.CimException] {
            #CIM not available on target (requires WMF 3.0+). Using DCOM (used by WMI)
            try { $Cim = New-CimSession -ComputerName $ComputerName -SessionOption $DCOM -ErrorAction Stop }
            catch { Write-Host $_.Exception.Message }
        }
    
        #Collect Printer Info
        Get-CimInstance -CimSession $Cim -Class Win32_printer -Property DeviceID, DriverName, PortName, SystemName
    
        #Best practice to store the original object.
        #No need to create a new one with a few properties when you do it during export anyways.
        #If you really need it, add "| Select-Object -Property DeviceID, DriverName, PortName, SystemName" to the previous line
    
    }
    
    #Export Results 
    $Objects | Select-Object -Property DeviceID, DriverName, PortName, SystemName |  Export-Csv - NoTypeInformation -Path c:\Scripts\output.csv