PowerShell script throws error but still produces results

0

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.

powershell
printing
remote-server
windows-server-2012-r2
asked on Stack Overflow Apr 20, 2017 by brehma • edited Apr 20, 2017 by TheMadTechnician

1 Answer

0

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.

answered on Stack Overflow Apr 21, 2017 by TheMadTechnician

User contributions licensed under CC BY-SA 3.0