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
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