I have a print server with about 50 printers installed with various drivers and not all configurations are set the same. I am moving printers around to new IP addresses based on a new IP schema, and I need to track each printer, its old IP, and the new IP. Then I need to capture the existing configurations for each one so I can add the printer and keep the settings the same as before.
So, here's the situation. I used the following:
PS C:\Users\a> Get-Printer | Where-Object -Property Name -match seattle | Get-PrintConfiguration
The output is:
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
If I shorten that line to:
PS C:\Users\a> Get-Printer | Where-Object -Property Name -match $city
The output is all 9 printers as I expect:
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
I should get a total of 9 printers, but I cannot understand why I get the error for 2 printers and get good results for the rest? The ultimate goal is to make this automated and log all the changes.
Get-Printer
and Get-PrintConfiguration
are really just wrappers for Get-CimInstance
calls to make things easier on us. We can use the CIM object to do all of this, and sometimes it works better that way. To get your printers, use this:
Get-CimInstance -ClassName MSFT_Printer -Namespace 'ROOT/StandardCimv2'
Then you can pipe that into a Where
statement (as provided by you) to refine the results to just the ones you want:
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)}
After that you can invoke the GetByPrinterName
method of the MSFT_PrinterConfiguration class to get the configuration for each printer (in a ForEach
loop) like this:
|%{Invoke-CimMethod -ClassName MSFT_PrinterConfiguration -Namespace 'ROOT/StandardCimv2' -MethodName GetByPrinterName -Arguments @{'PrinterName'=$_.Name} |% cmdletOutput}
So, if it were me I'd do something like this:
$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)
}
So what that does is gets all the printers, and filters for just the branch you specify. Then it makes an empty hashtable. Then it loops through the printers, and for each one it recovers the config info for that printer. Then it adds that to the printer object as the 'ConfigInfo' property. Lastly it adds a record to the hashtable for that printer's name, with the modified printer object as the value. So in the end you could do:
$Output['Seattle_Counter_Laser']
And that would show you the printer's info like what driver its running, and what the IP address is listed on the Port.
Or if you want to look it up by the IP in the PortName property you could do something like:
$Output.values|Where{$_.PortName -match '192.168.100.82'}
Then to get the configuration info you can do:
$Output['Seattle_Counter_Laser'].ConfigInfo
I would export that whole hashtable using Export-CliXml
and keep it someplace safe, because if things go sideways and the printers all stop working you have everything you need in that file to restore them back to how they are right now.
User contributions licensed under CC BY-SA 3.0