PowerShell 脚本抛出错误但仍产生结果

PowerShell script throws error but still produces results

我有一个打印服务器,大约有 50 台打印机安装了各种驱动程序,但并非所有配置都设置相同。我正在根据新的 IP 模式将打印机移动到新的 IP 地址,我需要跟踪每台打印机、它的旧 IP 和新 IP。然后我需要为每一个捕获现有配置,以便我可以添加打印机并保持设置与以前相同。

所以,情况是这样的。我使用了以下内容:

PS C:\Users\a> Get-Printer | Where-Object -Property Name -match seattle | Get-PrintConfiguration

输出为:

Get-PrintConfiguration : An error occurred while performing the specified operation.  See the error details for more information.
At line:1 char:60
+ Get-Printer | Where-Object -Property Name -match seattle | Get-PrintConfiguratio ...
+                                                            ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (MSFT_PrinterConfiguration:ROOT/StandardCi...erConfiguration) [Get-PrintConfiguration], CimException
+ FullyQualifiedErrorId : HRESULT 0x8000ffff,Get-PrintConfiguration

Get-PrintConfiguration : An error occurred while performing the specified operation.  See the error details for more information.
At line:1 char:60
+ Get-Printer | Where-Object -Property Name -match seattle | Get-PrintConfiguratio ...
+                                                            ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (MSFT_PrinterConfiguration:ROOT/StandardCi...erConfiguration) [Get-PrintConfiguration], CimException
+ FullyQualifiedErrorId : HRESULT 0x8000ffff,Get-PrintConfiguration


PrinterName     ComputerName    Collate    Color      DuplexingMode       
-----------     ------------    -------    -----      -------------       
Seattle_Coun...                 False      True       OneSided            
SeattleWhsLaser                 True       True       OneSided            
Seattle Ware...                 False      False      OneSided            
Seattle_Seco...                 True       False      OneSided            
Seattle_Test...                 True       True       OneSided            
SeattleCoun                     True       True       OneSided            
Seattle - SH...                 True       True       OneSided           

如果我将该行缩短为:

PS C:\Users\a> Get-Printer | Where-Object -Property Name -match $city 

如我所料,输出是全部 9 台打印机:

Name                           ComputerName    Type         DriverName                PortName        Shared   Published 
----                           ------------    ----         ----------                --------        ------   --------- 
Seattle_Test_Printer-Seattl...                 Local        HP Universal Printing PS  192.168.100.25  True     True      
Seattle_Second_Floor                           Local        HP Universal Printing ... IP_192.168.1... True     True      
Seattle_Counter_Laser                          Local        HP Universal Printing ... IP_192.168.1... True     False     
SeattleWhsLaser                                Local        HP Universal Printing ... 192.168.100.82  True     True      
SeattleCoun                                    Local        HP Universal Printing ... IP_192.168.1... True     True      
Seattle Warehouse ZDesigner...                 Local        ZDesigner 110XiIII Plu... 192.168.100.... True     True      
Seattle Upstairs OKI PCL6 C...                 Local        OKI PCL6 Class Driver     192.168.100.14  True     True      
Seattle - SHARP MX-5141N PCL6                  Local        SHARP MX-5141N PCL6       192.168.100.30  True     False     
Seattle (new) HP LaserJet P...                 Local        HP LaserJet P3011/P301... 192.168.100.25  True     True      

我应该总共得到 9 台打印机,但我不明白为什么我得到了 2 台打印机的错误,而其余的却得到了好的结果?最终目标是使其自动化并记录所有更改。

Get-PrinterGet-PrintConfiguration 实际上只是 Get-CimInstance 调用的包装器,使我们的工作更轻松。我们可以使用 CIM 对象来完成所有这些工作,有时这种方式效果更好。要获取您的打印机,请使用:

Get-CimInstance -ClassName MSFT_Printer -Namespace 'ROOT/StandardCimv2'

然后您可以将其通过管道传输到 Where 语句(由您提供)以将结果细化为您想要的结果:

Get-CimInstance -ClassName MSFT_Printer -Namespace 'ROOT/StandardCimv2' | where {($_.location -split '\.')[2] -eq $locationNumber -or ($_.sharename -match $city) -or ($_.name -match $city) -or ($_.location -match $city)}

之后,您可以调用 MSFT_PrinterConfiguration class 的 GetByPrinterName 方法来获取每台打印机的配置(在 ForEach 循环中),如下所示:

|%{Invoke-CimMethod -ClassName MSFT_PrinterConfiguration -Namespace 'ROOT/StandardCimv2' -MethodName GetByPrinterName -Arguments @{'PrinterName'=$_.Name} |% cmdletOutput}

所以,如果是我,我会这样做:

$Printers = Get-CimInstance -ClassName MSFT_Printer -Namespace 'ROOT/StandardCimv2' | where {($_.location -split '\.')[2] -eq $locationNumber -or ($_.sharename -match $city) -or ($_.name -match $city) -or ($_.location -match $city)}
$Output = @{}
ForEach($Printer in $Printers){
    $Config = Invoke-CimMethod -ClassName MSFT_PrinterConfiguration -Namespace 'ROOT/StandardCimv2' -MethodName GetByPrinterName -Arguments @{'PrinterName'=$Printer.Name} |% cmdletOutput
    $Printer | Add-Member 'ConfigInfo' $Config
    $Output.add($Printer.Name,$Printer)
}

所以它的作用是获取所有打印机,并仅针对您指定的分支进行过滤。然后它创建一个空的哈希表。然后它遍历打印机,并为每一台打印机恢复该打印机的配置信息。然后它将其作为 'ConfigInfo' 属性 添加到打印机对象。最后,它向该打印机名称的哈希表中添加一条记录,并将修改后的打印机对象作为值。所以最后你可以这样做:

$Output['Seattle_Counter_Laser']

这会向您显示打印机的信息,例如它的驱动程序 运行,以及端口上列出的 IP 地址。

或者如果你想通过 PortName 属性 中的 IP 查找它,你可以这样做:

$Output.values|Where{$_.PortName -match '192.168.100.82'}

然后要获取配置信息,您可以执行以下操作:

$Output['Seattle_Counter_Laser'].ConfigInfo

我将使用 Export-CliXml 导出整个哈希表并将其保存在安全的地方,因为如果事情发生意外并且打印机全部停止工作,您将在该文件中拥有将它们恢复到原来状态所需的一切现在。