CIM与WMI返回信息不一致:子网计算机打印机获取问题咨询
解决CIM并行获取打印机信息时丢失整台机器数据的问题
看起来你已经发现CIM比传统WMI快很多,但遇到了两个头疼的问题:返回的信息和WMI不一致,甚至会直接丢失整台计算机的记录。我来帮你拆解一下问题原因,再给出具体的解决脚本。
首先,丢失整台机器信息最常见的原因是CIM连接失败但没有被捕获——WMI通常会把错误信息返回给你,但CIM如果处理不当,连接不上的机器就直接被跳过了,连个错误记录都没有。另外,CIM默认返回的属性集可能比WMI少,这也会导致信息不一致。
第一步:捕获连接错误,记录所有机器
先修改你的脚本,加入错误捕获逻辑,这样不管机器能不能连接,都会留下记录:
$ComputerList = Get-Content -Path c:\Scripts\input.txt $Results = @() foreach ($ComputerName in $ComputerList) { try { # 显式指定要获取的属性,确保和WMI返回一致 $SelectedProps = 'Name', 'DriverName', 'PortName', 'Shared', 'ShareName', 'Default' $Printers = Get-CimInstance -ClassName Win32_Printer -ComputerName $ComputerName -Property $SelectedProps -ErrorAction Stop foreach ($Printer in $Printers) { $Results += [PSCustomObject]@{ ComputerName = $ComputerName PrinterName = $Printer.Name DriverName = $Printer.DriverName PortName = $Printer.PortName IsShared = $Printer.Shared ShareName = $Printer.ShareName IsDefault = $Printer.Default } } } catch { # 把连接失败的机器也加入结果 $Results += [PSCustomObject]@{ ComputerName = $ComputerName PrinterName = "⚠️ 连接失败" ErrorMessage = $_.Exception.Message DriverName = $null PortName = $null IsShared = $null ShareName = $null IsDefault = $null } } } $Results | Export-Csv -Path "C:\Scripts\Printer_Report.csv" -NoTypeInformation
第二步:用CIM真正的并行处理提升效率
如果你想充分利用CIM的并行能力(比foreach循环快得多),可以用Invoke-CimCommand来批量处理,同时捕获所有错误:
$ComputerList = Get-Content -Path c:\Scripts\input.txt # 创建CIM会话选项(根据你的环境选择DCOM或Wsman,一般内网用DCOM) $SessionOption = New-CimSessionOption -Protocol DCOM # 创建CIM会话,同时捕获创建失败的机器 $CimSessions = New-CimSession -ComputerName $ComputerList -SessionOption $SessionOption -ErrorAction SilentlyContinue -ErrorVariable SessionErrors # 并行执行命令获取打印机信息 $PrinterData = Invoke-CimCommand -CimSession $CimSessions -ScriptBlock { # 在远程机器上执行的逻辑,同样指定属性 Get-CimInstance -ClassName Win32_Printer -Property 'Name', 'DriverName', 'PortName', 'Shared', 'ShareName', 'Default' } -ErrorAction SilentlyContinue -ErrorVariable CommandErrors # 整理正常返回的结果 $FinalResults = $PrinterData | Select-Object ` @{Name='ComputerName'; Expression={$_.PSComputerName}}, @{Name='PrinterName'; Expression={$_.Name}}, DriverName, PortName, @{Name='IsShared'; Expression={$_.Shared}}, ShareName, @{Name='IsDefault'; Expression={$_.Default}} # 添加会话创建失败的机器记录 foreach ($err in $SessionErrors) { $FinalResults += [PSCustomObject]@{ ComputerName = $err.TargetObject PrinterName = "⚠️ 会话创建失败" ErrorMessage = $err.Exception.Message DriverName = $null PortName = $null IsShared = $null ShareName = $null IsDefault = $null } } # 添加命令执行失败的机器记录 foreach ($err in $CommandErrors) { $FinalResults += [PSCustomObject]@{ ComputerName = $err.TargetObject PrinterName = "⚠️ 命令执行失败" ErrorMessage = $err.Exception.Message DriverName = $null PortName = $null IsShared = $null ShareName = $null IsDefault = $null } } # 输出结果到CSV $FinalResults | Export-Csv -Path "C:\Scripts\Parallel_Printer_Report.csv" -NoTypeInformation # 清理CIM会话 Remove-CimSession -CimSession $CimSessions
关键注意事项
- 错误处理是核心:之前丢失整台机器信息,大概率是因为没有捕获CIM连接/执行的错误,上面的脚本会把所有失败的机器都记录下来,你可以清楚看到哪些机器出了问题。
- 属性显式指定:CIM默认返回的属性可能比WMI少,所以一定要用
-Property参数指定你需要的所有属性,确保和WMI返回的信息一致。 - 会话重用:创建CIM会话比每次调用
Get-CimInstance重新连接高效得多,尤其是处理大量机器时,一定要重用会话。
内容的提问来源于stack exchange,提问作者fausty
相关产品推荐
相关产品推荐

