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-Printer
和 Get-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
导出整个哈希表并将其保存在安全的地方,因为如果事情发生意外并且打印机全部停止工作,您将在该文件中拥有将它们恢复到原来状态所需的一切现在。
我有一个打印服务器,大约有 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-Printer
和 Get-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
导出整个哈希表并将其保存在安全的地方,因为如果事情发生意外并且打印机全部停止工作,您将在该文件中拥有将它们恢复到原来状态所需的一切现在。