Back to top

FREE eBook: The Most USEFUL PowerShell CmdLets and more…

Grab a copy!

How To List Installed Printers Using PowerShell

How To List Installed Printers Using PowerShell Featured
Approx Reading Time: 27 minutes

If you work for a client with lots of network printers then you really know how important is to be efficient managing any number of printers.

To list installed printers using PowerShell we can use:

  • Get-Printer CmdLet,
  • Win32_Printer WMI Class,
  • CIM_Printer CIM Class.

Get List Of Installed Printers – Solutions

Here are a few solutions to list the installed printers using PowerShell.

Solution 1 – Get List Of Installed Printers On Local Machine

PowerShell is very rich to give us wanted information when we talk about the list of installed printers on the local machine. So we can use CmdLet, WMI or CIM classes. Here I will show you a few solutions.

Get-Printer CmdLet

We can call native PowerShell Get-Printer CmdLet to get the list of installed printers on the local machine.

Get-Printer | Select-Object Name, ComputerName, Type, DriverName, Shared, Published | Out-GridView

Here is the resultset.

List of installed printers on local machine using Get-Printer CmdLet

Win32_Printer WMI Class

We can use the Win32_Printer WMI Class to get the list of installed printers on the local machine.

Get-CimInstance -ClassName Win32_Printer -ErrorAction Stop | Out-GridView

Here is the resultset.

List of installed printers on local machine using Win32_Printer WMI Class

CIM_Printer CIM Class

Finally, we can use CIM_Printer CIM Class to get the list of installed printers on the local machine.

Get-CimInstance -ClassName CIM_Printer -ErrorAction Stop | Out-GridView 

Here is the resultset.

List of installed printers on local machine using CIM_Printer CIM Class

Solution 2 – Get List Of Installed Printers For The List Of Servers (Remote Computers)

For the list of computers, we can use the same calls as for the previous solution only to use the ComputerName parameter and add the list of servers as a txt file.

Create the list of servers in the text file and save in, for example, C:\Temp folder. We basically load the content of the text file using Get-Content CmdLet and PowerShell will go through the list and run the same command as in the previous solution for each server on the list.

Get-Printer CmdLet

We call Get-Printer and provide the value for the ComputerName parameter.

Get-Printer -ComputerName (Get-Content -Path 'C:\Temp\Servers.txt') | Select-Object Name, ComputerName, Type, DriverName, Shared, Published | Out-GridView

Win32_Printer WMI Class

We use the Win32_Printer WMI Class combined with the ComputerName parameter that has been fed from the text file with the list of servers.

Get-CimInstance -ClassName Win32_Printer -ErrorAction Stop -ComputerName (Get-Content -Path 'C:\Temp\Servers.txt') | Out-GridView

Here is the resultset.

Win32_Printer WMI Class resultset for the list of servers

CIM_Printer CIM Class

We use the CIM_Printer CIM Class combined with the ComputerName parameter that has been fed from the text file with the list of servers.

Get-CimInstance -ClassName CIM_Printer -ErrorAction Stop -ComputerName (Get-Content -Path 'C:\Temp\Servers.txt') | Out-GridView 

Here is the resultset.

CIM_Printer CIM Class resultset for the list of servers

I do not have servers in my home network so in order to simulate one I have created a very simple input list of servers in a text file just copying the localhost value several times.

Servers.txt file content

Solution 3 – Write Own PowerShell CmdLet ( Get-Printers )

I have written my own Get-Printers CmdLet that I will explain in the minute.

This approach takes a little bit longer time but gives us more benefits in the long run so it is my preferred way and we can combine this CmdLet with the library of CmdLets in Efficiency Booster PowerShell Project.

Here is a sample call to Get-Printers CmdLet:

Get-Printers -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

Here is the resultset of a call to Get-Printers CmdLet:

Get-Printers CmdLet resultset

INFO: I have written two PowerShell Add-on functions ( Get-CIMClassProperty and Select-CIMClassAllProperties) that help us working with WMI and CIM classes. First list all the properties and datatypes of WMI or CIM classes and the second one makes the select statements with all the properties for the WMI or CIM class. How To List CIM Or WMI Class All Properties And Their Datatypes With PowerShell AND How To Write Select Statement For All Properties Of CIM Or WMI Class With PowerShell.

Get-Printers CmdLet Explained

Get-Printers CmdLet collects installed printers for the list of servers and this CmdLet belongs to Efficiency Booster PowerShell Project. This project is the library of different CmdLets that can help us IT personal to do our everyday tasks more efficiently and accurately.

Source code for Get-Printers CmdLet can be downloaded from this zip file so please feel free to download it and it would be easier for you to follow me along.

Get-Printers CmdLet is part of Common module and if you have downloaded the source code it can be found in the folder …\[My] Documents\WindowsPowerShell\Modules\03common

INFO: If you want to know how to install and configure Efficiency Booster PowerShell Project files please read the following article: How To Install And Configure PowerShell: CmdLets, Modules, Profiles.

Get-Printers CmdLet – Input Parameters

As input parameters we have:

  • computers – it is a list of servers passed as input parameter with default value ‘localhost’ and accepts both pipeline options. Parameter belongs to the “ServerNames” parameter set. The “ServerNames” parameter set is the default parameter set.
  • filename – it is the name of the text file with the list of servers and represents an alternative option to the “computers” parameter. The parameter belongs to the “FileName” parameter set.
  • status – has three values (All, Offline, Error). Error returns only printers with error, Offline returns list of offline printers, All is self-explanatory. The default value is Error.
  • errorlog – switch datatype and when turned on it will write errors into an external error log file using Write-ErrorLog CmdLet. The error log file is located in the PSLogs folder of [My] Documents.
  • client – it is a mandatory input parameter and by convention, I use two letters for client shortcode (for example, OK = O client, BK = B client, etc.). This parameter value is part of the filename parameter naming convention.
  • solution – it is a mandatory input parameter and by convention, I use two-three letters for solution shortcode (for example, FIN = Financial solution, HR = HR solution, etc.).

The naming convention for the filename parameter is as follows: Client + Solution + Text.txt. The text file should be located in …[My] Documents\WindowsPowerShell\Modules\01servers folder.

For example:

  • OKFINTestServers.txt – List of test environment servers for OK client and FIN solution.
  • OKFINProdServers.txt – List of production environment servers for OK client and FIN solution.
  • OKFINAllServers.txt – List of all servers for OK client and FIN solution.

INFO: To get a deeper explanation about client and solution input parameters please read these two sections Parameter clientParameter solution.

INFO: In order to customize the installation of CmdLet to your needs and set up necessary CSV file please read the following article How To Install And Configure PowerShell: CmdLets, Modules, Profiles

Here is the parameters definition code:

Function Get-Printers {
[CmdletBinding(DefaultParametersetName="ServerNames")]
param (
    [Parameter( ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true,
                ParameterSetName="ServerNames",
                HelpMessage="List of computer names separated by commas.")]
    [Alias('hosts')] 
    [string[]]$computers = 'localhost',
    
    [Parameter( ParameterSetName="FileName",
                HelpMessage="Name of txt file with list of servers. Txt file should be in 01servers folder.")] 
    [string]$filename,
    
    [Parameter(Mandatory=$false,
                HelpMessage="Status of printer. Values (All, Offline, Error).")]
    [ValidateSet("All", "Offline", "Error")] 
    [string]$status = 'Error',
    
    [Parameter( Mandatory=$false,
                HelpMessage="Write to error log file or not.")]
    [switch]$errorlog,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Client for example OK = O client, BK = B client")]
    [string]$client,
     
    [Parameter(Mandatory=$true,
                HelpMessage="Solution, for example FIN = Financial, HR = Human Resource")]
    [string]$solution     
)
}

INFO: To know more about PowerShell Parameters and Parameter Sets with some awesome examples please read the following articles How To Create Parameters In PowerShell and How To Use Parameter Sets In PowerShell Functions.

INFOPowerShell Pipelining is a very important concept and I highly recommend you to read the article written on the subject. How PowerShell Pipeline Works. Here I have shown in many examples the real power of PowerShell using the Pipelining.

BEGIN Block

In the BEGIN block we:

  • If the FileName parameter set has been used we test if text file with a list of servers exists.
  • If the file exists read the file and create the list of servers as a string array in the $computers variable.
  • … and if not write a warning with information to the caller to create the file.
BEGIN {

    if ( $PsCmdlet.ParameterSetName -eq "FileName") {

        if ( Test-Path -Path "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" -PathType Leaf ) {
            Write-Verbose "Read content from file: $filename"
            $computers = Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" )        
        } else {
            Write-Warning "This file path does NOT exist: $home\Documents\WindowsPowerShell\Modules\01servers\$filename"
            Write-Warning "Create file $filename in folder $home\Documents\WindowsPowerShell\Modules\01servers with list of server names."
            break;
        } 
    }            
}

PROCESS Block

In the PROCESS block we run this block of code for each server passed into the pipeline or read from the text file:

  • We replace the localhost default value for the local server with the actual name of the local machine.
  • We use Get-ComputerInfo CmdLet to read additional data about each server (name, environment, logical name, IP address).
  • We implement Error Handling using try-catch blocks and writing errors in an external text file using Write-ErrorLog CmdLet.
  • We use switch combined with the status input parameter to process each status-type printers separately calling Get-CimInstance CmdLet.
  • We use PowerShell splatting to prepare the input parameters for the next call of Get-CimInstance CmdLet.
  • We use the Win32_Printer WMI class to get printers’ information.
  • We prepare the resultset of Get-Printers CmdLet.

Please notice these three features in the PROCESS block.

Splatting

We have used splatting several times. First when we prepare the call to Get-CimInstance CmdLet, and second when we prepare the resultset.

Splatting helps us to have a more neat and understandable code.

Here is a call to Get-CimInstance CmdLet and use of splatting:

$params = @{ 'ComputerName'=$computer;
             'Class'='Win32_Printer';
             'ErrorAction'='Stop';
             'Filter'= "ExtendedPrinterStatus='7'"}

$Printers = Get-CimInstance @params | 
             Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
             PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;

Here is the second use of splatting when creating the resultset.

$properties = @{ 'Environment'=$env;
                 'Logical name'=$logicalname;
                 'Server name'=$Printer.SystemName;
            	 'Name'=$Printer.Name;
                 'Location'=$Printer.Location;
                 'Job count since last reset'=$Printer.JobCountSinceLastReset;
                 'Status'=$Printer.Status;
                 'Printer status'=$Printer.PrinterStatus;
                 'Printer state'=$Printer.PrinterState;
                 'Detected error state'=$Printer.DetectedErrorState;
                 'Extended detected error state'=$Printer.ExtendedDetectedErrorState;
                 'Extended printer status'=$Printer.ExtendedPrinterStatus;
                 'Port name'=$Printer.PortName;
                 'Driver name'=$Printer.DriverName;
                 'Network'=$Printer.Network;
                 'Shared'=$Printer.Shared;
                 'Share name'=$Printer.ShareName;
                 'Spool enabled'=$Printer.SpoolEnabled;
                 'Work offline'=$Printer.WorkOffline;
                 'Default'=$Printer.Default;
                 'IP'=$ip;
                 'Collected'=(Get-Date -UFormat %Y.%m.%d' '%H:%M:%S)}
                
$obj = New-Object -TypeName PSObject -Property $properties
$obj.PSObject.TypeNames.Insert(0,'Report.Printers')

Type Name Of The Resultset Objects

Notice the name of the resultset (Report.Printers).

$obj.PSObject.TypeNames.Insert(0,'Report.Printers')

So if we call PowerShell Get-Member CmdLet to get the type of resultset for Get-Printers CmdLet we will get Report.Printers type and not standard PowerShell PSObject type.

Get-Printers -client "OK" -solution "FIN" -status "All" | Get-Member 

Here is the resultset:

Report.Printers Type Name for Get-Printers CmdLet resultset

Type Name of resultset gives us a possibility to further expend the use of resultset. For example, we can use MS SQL Database and create table Printers based on resultset type name ( Report.Printers ) where we can record the resultset and use MS SQL Reporting Services to show the results collected over a certain period of time.

List Offline Printers And Printers With Errors

We use the property ExtendedPrinterStatus=’7′ to get all offline printers and we use ExtendedPrinterStatus=’9′ to get all printers with errors.

Win32_Printer WMI Class provides us with ExtendedPrinterStatus property.

Here is the PROCESS block source code:

PROCESS { 

    foreach ($computer in $computers ) {
        
        if ( $computer -eq 'localhost' ) {
            $computer = $env:COMPUTERNAME
        }
        
        $computerinfo = Get-ComputerInfo -computername $computer -client $client -solution $solution
        $hostname = $computerinfo.hostname
        $env = $computerinfo.environment
        $logicalname = $computerinfo.logicalname
        $ip = $computerinfo.ipaddress
        
        try {
            Write-Verbose "Start processing: $computer - $env - $logicalname"
            Write-Verbose "Start Win32_Printer processing..."
            $Printers = $null
            $Printer = $null
            $obj = $null
            
            switch($status) {
                'All' {
                    
                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop'}

                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                    break
                }
                'Offline' {

                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop';
                         'Filter'= "ExtendedPrinterStatus='7'"}

                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                    break
                }
                default {
                    
                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop';
                         'Filter'= "ExtendedPrinterStatus='9'"}
 
                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                }
            }
            
            Write-Verbose "Finish Win32_Printer processing..."
            
            if ($Printers) {
                foreach ($Printer in $Printers) {
                    Write-Verbose "Start processing Printer: $Printer"
                   
                    $properties = @{ 'Environment'=$env;
                                     'Logical name'=$logicalname;
                                     'Server name'=$Printer.SystemName;
            	                     'Name'=$Printer.Name;
                                     'Location'=$Printer.Location;
                                     'Job count since last reset'=$Printer.JobCountSinceLastReset;
                                     'Status'=$Printer.Status;
                                     'Printer status'=$Printer.PrinterStatus;
                                     'Printer state'=$Printer.PrinterState;
                                     'Detected error state'=$Printer.DetectedErrorState;
                                     'Extended detected error state'=$Printer.ExtendedDetectedErrorState;
                                     'Extended printer status'=$Printer.ExtendedPrinterStatus;
                                     'Port name'=$Printer.PortName;
                                     'Driver name'=$Printer.DriverName;
                                     'Network'=$Printer.Network;
                                     'Shared'=$Printer.Shared;
                                     'Share name'=$Printer.ShareName;
                                     'Spool enabled'=$Printer.SpoolEnabled;
                                     'Work offline'=$Printer.WorkOffline;
                                     'Default'=$Printer.Default;
                                     'IP'=$ip;
                                     'Collected'=(Get-Date -UFormat %Y.%m.%d' '%H:%M:%S)}
                
                    $obj = New-Object -TypeName PSObject -Property $properties
                    $obj.PSObject.TypeNames.Insert(0,'Report.Printers')

                    Write-Output $obj
                    Write-Verbose "Finish processing Printer: $Printer"
                }
            }
            
            Write-Verbose "Finish processing: $computer - $env - $logicalname"
            
        } catch {
            Write-Warning "Computer failed: $computer - $env - $logicalname Printer failed: $Printer"
            Write-Warning "Error message: $_"

            if ( $errorlog ) {

                $errormsg = $_.ToString()
                $exception = $_.Exception
                $stacktrace = $_.ScriptStackTrace
                $failingline = $_.InvocationInfo.Line
                $positionmsg = $_.InvocationInfo.PositionMessage
                $pscommandpath = $_.InvocationInfo.PSCommandPath
                $failinglinenumber = $_.InvocationInfo.ScriptLineNumber
                $scriptname = $_.InvocationInfo.ScriptName

                Write-Verbose "Start writing to Error log."
                Write-ErrorLog -hostname $computer -env $env -logicalname $logicalname -errormsg $errormsg -exception $exception -scriptname $scriptname -failinglinenumber $failinglinenumber -failingline $failingline -pscommandpath $pscommandpath -positionmsg $pscommandpath -stacktrace $stacktrace
                Write-Verbose "Finish writing to Error log."
            }
        }
    }
}

INFO: To learn about PowerShell Error Handling and code debugging please read the following articles: How To Log PowerShell Errors And Much More and How To Debug PowerShell Scripts.

END Block

END block is empty.

INFO: To understand BEGINPROCESS and END blocks in PowerShell please read PowerShell Function Begin Process End Blocks Explained With Examples.

Comment-Based Help Section

For every one of my own CmdLets, I write Comment-Based help as well.

INFO: If you want to learn how to write comment-based Help for your own PowerShell Functions and Scripts please read these articles How To Write PowerShell Help (Step by Step). In this article How To Write PowerShell Function’s Or CmdLet’s Help (Fast), I explain the PowerShell Add-on that help us to be fast with writing help content.

How To Use Get-Printers CmdLet – Tips

To get a list of installed printers for the local machine we just call Get-Printers CmdLet and provide values for mandatory parameters (client and solution, optionally choose printer status):

Get-Printers -client "OK" -solution "FIN" -status "All"

Here is the resultset:

Get-Printers CmdLet resultset for the local machine

As we have seen in the solution section of this article we can call Get-Printers CmdLet for the list of servers:

Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

Here is the resultset for the list of servers.

Get-Printers CmdLet resultset

We can PowerShell pipeline result from Get-Printers CmdLet into Save-ToExcel CmdLet and get resultset as an Excel Sheet:

Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -status "All" -Verbose | Save-ToExcel -errorlog -ExcelFileName "Get-Printers" -title "Get printers info of servers in Financial solution for " -author "Dejan Mladenovic" -WorkSheetName "Printer Info" -client "OK" -solution "FIN" 

Here is the Excel Sheet result:

Get-Printers CmdLet resultset as Excel Sheet

Bonus Tip

We can schedule a call to Get-Printers CmdLet with all the printers with errors so we can fix the errors and have this as a maintenance routine.

Let me tell you a short story from the fields. I got the call that the user of the application cannot print the reports. We went to the user’s office and we have recreated the failure.

I have started the fail search with the first printing sample document from the Word and that worked. So I know the printer is working. Next, I tried to print some other reports from the same application that was failing and that worked as well.

When I run the failing report again and checked the printer queue I could not see the printing job in the queue. I have turned the investigation from the local machine into the application server and there I have found the printing job waiting in the queue and being blocked by some earlier printing jobs that were jamming the printing queue.

Conclusion: Application can print reports sending them directly to the printer from the client application and for some reports client application sends printing requests to the application server that will print the reports to the same printer and not from the local user’s machine.

In order to have the control which printers were failing I have created Get-Printers CmdLet and scheduled it to send me weekly reports of printers with errors so I can clean the printing queue and make these printers available for user printing requests.

Analysis

In the printer list below we can see that one printer has printer-state value = 131 072.

Get-Printers CmdLet resultset

If we look at the table below we will see that value = 131 072 means Toner low. So I think I should buy some toners for that printer ASAP.

Status Code (Decimal)Status Code (Hex)Description
00Printer ready
11Printer paused
22Printer error
44Printer pending deletion
88Paper jam
1610Out of paper
3220Manual feed
6440Paper problem
12880Printer offline
256100IO active
512200Printer busy
1024400Printing
2048800Printer output bin full
40961000Not available.
81922000Waiting
163844000Processing
327688000Initializing
6553610000Warming up
13107220000Toner low
26214440000No toner
52428880000Page punt
1048576100000User intervention
2097152200000Out of memory
4194304400000Door open
8388608800000Server unknown
167772161000000Power save
Printer Status Codes

Useful PowerShell Printing Articles

Here are some useful articles and resources:

Get-Printers CmdLet Source Code

DISCLAIMERGet-Printers function is part of the Efficiency Booster PowerShell Project and as such utilize other CmdLets that are part of the same project. So the best option for you in order for this function to work without any additional customization is to download the source code of the whole project from here.

INFO: My best advice to every PowerShell scripter is to learn writing own PowerShell Advanced Functions and CmdLets and I have written several articles explaining this, so please read them. How To Create A Custom PowerShell CmdLet (Step By Step). Here I explain how to use PowerShell Add-on Function to be faster in writing PowerShell Functions How To Write Advanced Functions Or CmdLets With PowerShell (Fast).

Here is the source code of the whole Get-Printers CmdLet:

<#
.SYNOPSIS
Gets Printers info for list of servers.
.DESCRIPTION
Gets Printers info for list of servers. 
List of servers is in txt file in 01servers folder or list of strings with names of computers.
CmdLet has two ParameterSets one for list of computers from file and another from list of strings as computer names.

Errors will be saved in log folder PSLogs with name Error_Log.txt. Parameter errorlog controls logging of errors in log file.

Get-Printers function uses Get-CimInstance -Class Win32_Printer PowerShell function to get Printer info.

Result shows following columns: Environment (PROD, Acceptance, Test, Course...), 
LogicalName (Application, web, integration, FTP, Scan, Terminal Server...), Server name, 
Name , Location, Job count since last reset, Status, Printer status, Printer state, Detected error state, 
Extended detected error state, Extended printer status, Port name, Driver name, Network, Shared, 
Share name, Spool enabled, Work offline, Default, IP, Collected
                    
.PARAMETER computers
List of computers that we want to get Printer info from. Parameter belongs to default Parameter Set = ServerNames.
.PARAMETER filename
Name of txt file with list of servers that we want to check Printer info. .txt file should be in 01servers folder.
Parameter belongs to Parameter Set = FileName.
.PARAMETER status
Filter list of printers by status. Default value for status is Error. That means only show printers with Error status.
Other valid values are: All and Offline.
.PARAMETER errorlog
Switch parameter that sets to write to log or not to write to log. Error file is in PSLog folder with name Error_Log.txt.
.PARAMETER client
OK - O client
BK - B client
etc.
.PARAMETER solution
FIN - Financial solution 
HR - Human resource solution
etc. 

.EXAMPLE
Get-Printers -client "OK" -solution "FIN"

Description
---------------------------------------
Test of default parameter with default value ( computers = 'localhost' ) in default ParameterSet = ServerName.

.EXAMPLE
Get-Printers -client "OK" -solution "FIN" -Verbose

Description
---------------------------------------
Test of Verbose parameter. NOTE: Notice how localhost default value of parameter computers replaces with name of server.

.EXAMPLE
'ERROR' | Get-Printers -client "OK" -solution "FIN" -errorlog

Description
---------------------------------------
Test of errorlog parameter. There is no server with name ERROR so this call will fail and write to Error log since errorlog switch parameter is on. Look Error_Log.txt file in PSLogs folder.

.EXAMPLE
Get-Printers -computers 'APP100001' -client "OK" -solution "FIN" -errorlog

Description
---------------------------------------
Test of computers parameter with one value. Parameter accepts array of strings.

.EXAMPLE
Get-Printers -computers 'APP100001', 'APP100002' -client "OK" -solution "FIN" -errorlog -Verbose

Description
---------------------------------------
Test of computers parameter with array of strings. Parameter accepts array of strings.

.EXAMPLE
Get-Printers -hosts 'APP100001' -client "OK" -solution "FIN" -errorlog

Description
---------------------------------------
Test of computers paramater alias hosts.

.EXAMPLE
Get-Printers -computers (Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" )) -client "OK" -solution "FIN" -errorlog -Verbose

Description
---------------------------------------
Test of computers parameter and values for parameter comes from .txt file that has list of servers.

.EXAMPLE
'APP100001' | Get-Printers -client "OK" -solution "FIN" -errorlog

Description
---------------------------------------
Test of pipeline by value of computers parameter.

.EXAMPLE
'APP100001', 'APP100002' | Get-Printers -client "OK" -solution "FIN" -errorlog -Verbose

Description
---------------------------------------
Test of pipeline by value with array of strings of computers parameter.

.EXAMPLE
'APP100001', 'APP100002' | Select-Object @{label="computers";expression={$_}} | Get-Printers -client "OK" -solution "FIN" -errorlog

Description
---------------------------------------
Test of values from pipeline by property name (computers).

.EXAMPLE
Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" ) | Get-Printers -client "OK" -solution "FIN" -errorlog -Verbose

Description
---------------------------------------
Test of pipeline by value that comes as content of .txt file with list of servers.

.EXAMPLE
Help Get-Printers -Full

Description
---------------------------------------
Test of Powershell help.

.EXAMPLE
Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose

Description
---------------------------------------
This is test of ParameterSet = FileName and parameter filename. There is list of servers in .txt file.

.EXAMPLE
Get-Printers -filename "OKFINserverss.txt" -errorlog -client "OK" -solution "FIN" -Verbose

Description
---------------------------------------
This is test of ParameterSet = FileName and parameter filename. This test will fail due to wrong name of the .txt file with warning message "WARNING: This file path does NOT exist:".

.INPUTS
System.String

Computers parameter pipeline both by Value and by Property Name value and has default value of localhost. (Parameter Set = ComputerNames)
Filename parameter does not pipeline and does not have default value. (Parameter Set = FileName)
.OUTPUTS
System.Management.Automation.PSCustomObject

Get-Print returns PSCustomObjects which has been converted from PowerShell function Get-WmiObject -Class Win32_Printer
Result shows following columns: Environment (PROD, Acceptance, Test, Course...), 
LogicalName (Application, web, integration, FTP, Scan, Terminal Server...), Server name, 
Name , Location, Job count since last reset, Status, Printer status, Printer state, Detected error state, 
Extended detected error state, Extended printer status, Port name, Driver name, Network, Shared, 
Share name, Spool enabled, Work offline, Default, IP, Collected

.NOTES
FunctionName : Get-Printers
Created by   : Dejan Mladenovic
Date Coded   : 10/31/2018 19:06:41
More info    : https://improvescripting.com/

.LINK 
https://improvescripting.com/how-to-list-installed-printers-using-powershell
Get-CimInstance -Class Win32_Printer
#>
Function Get-Printers {
[CmdletBinding(DefaultParametersetName="ServerNames")]
param (
    [Parameter( ValueFromPipeline=$true,
                ValueFromPipelineByPropertyName=$true,
                ParameterSetName="ServerNames",
                HelpMessage="List of computer names separated by commas.")]
    [Alias('hosts')] 
    [string[]]$computers = 'localhost',
    
    [Parameter( ParameterSetName="FileName",
                HelpMessage="Name of txt file with list of servers. Txt file should be in 01servers folder.")] 
    [string]$filename,
    
    [Parameter(Mandatory=$false,
                HelpMessage="Status of printer. Values (All, Offline, Error).")]
    [ValidateSet("All", "Offline", "Error")] 
    [string]$status = 'Error',
    
    [Parameter( Mandatory=$false,
                HelpMessage="Write to error log file or not.")]
    [switch]$errorlog,
    
    [Parameter(Mandatory=$true, 
                HelpMessage="Client for example OK = O client, BK = B client")]
    [string]$client,
     
    [Parameter(Mandatory=$true,
                HelpMessage="Solution, for example FIN = Financial, HR = Human Resource")]
    [string]$solution     
)

BEGIN {

    if ( $PsCmdlet.ParameterSetName -eq "FileName") {

        if ( Test-Path -Path "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" -PathType Leaf ) {
            Write-Verbose "Read content from file: $filename"
            $computers = Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\$filename" )        
        } else {
            Write-Warning "This file path does NOT exist: $home\Documents\WindowsPowerShell\Modules\01servers\$filename"
            Write-Warning "Create file $filename in folder $home\Documents\WindowsPowerShell\Modules\01servers with list of server names."
            break;
        } 
    }    
        
}
PROCESS { 

    foreach ($computer in $computers ) {
        
        if ( $computer -eq 'localhost' ) {
            $computer = $env:COMPUTERNAME
        }
        
        $computerinfo = Get-ComputerInfo -computername $computer -client $client -solution $solution
        $hostname = $computerinfo.hostname
        $env = $computerinfo.environment
        $logicalname = $computerinfo.logicalname
        $ip = $computerinfo.ipaddress
        
        try {
            Write-Verbose "Start processing: $computer - $env - $logicalname"
            Write-Verbose "Start Win32_Printer processing..."
            $Printers = $null
            $Printer = $null
            $obj = $null
            
            switch($status) {
                'All' {
                    
                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop'}

                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                    break
                }
                'Offline' {

                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop';
                         'Filter'= "ExtendedPrinterStatus='7'"}

                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                    break
                }
                default {
                    
                    $params = @{ 'ComputerName'=$computer;
                         'Class'='Win32_Printer';
                         'ErrorAction'='Stop';
                         'Filter'= "ExtendedPrinterStatus='9'"}
 
                    $Printers = Get-CimInstance @params | 
                                    Select-Object DetectedErrorState, DriverName, ExtendedDetectedErrorState, ExtendedPrinterStatus, JobCountSinceLastReset, Location, Name, Network, PortName, PrinterState, 
                                    PrinterStatus, Shared, ShareName, SpoolEnabled, Status, SystemName, WorkOffline, Default;
                }
            }
            
            Write-Verbose "Finish Win32_Printer processing..."
            
            if ($Printers) {
                foreach ($Printer in $Printers) {
                    Write-Verbose "Start processing Printer: $Printer"
                   
                    $properties = @{ 'Environment'=$env;
                                     'Logical name'=$logicalname;
                                     'Server name'=$Printer.SystemName;
            	                     'Name'=$Printer.Name;
                                     'Location'=$Printer.Location;
                                     'Job count since last reset'=$Printer.JobCountSinceLastReset;
                                     'Status'=$Printer.Status;
                                     'Printer status'=$Printer.PrinterStatus;
                                     'Printer state'=$Printer.PrinterState;
                                     'Detected error state'=$Printer.DetectedErrorState;
                                     'Extended detected error state'=$Printer.ExtendedDetectedErrorState;
                                     'Extended printer status'=$Printer.ExtendedPrinterStatus;
                                     'Port name'=$Printer.PortName;
                                     'Driver name'=$Printer.DriverName;
                                     'Network'=$Printer.Network;
                                     'Shared'=$Printer.Shared;
                                     'Share name'=$Printer.ShareName;
                                     'Spool enabled'=$Printer.SpoolEnabled;
                                     'Work offline'=$Printer.WorkOffline;
                                     'Default'=$Printer.Default;
                                     'IP'=$ip;
                                     'Collected'=(Get-Date -UFormat %Y.%m.%d' '%H:%M:%S)}
                
                    $obj = New-Object -TypeName PSObject -Property $properties
                    $obj.PSObject.TypeNames.Insert(0,'Report.Printers')

                    Write-Output $obj
                    Write-Verbose "Finish processing Printer: $Printer"
                }
            }
            
            Write-Verbose "Finish processing: $computer - $env - $logicalname"
            
        } catch {
            Write-Warning "Computer failed: $computer - $env - $logicalname Printer failed: $Printer"
            Write-Warning "Error message: $_"

            if ( $errorlog ) {

                $errormsg = $_.ToString()
                $exception = $_.Exception
                $stacktrace = $_.ScriptStackTrace
                $failingline = $_.InvocationInfo.Line
                $positionmsg = $_.InvocationInfo.PositionMessage
                $pscommandpath = $_.InvocationInfo.PSCommandPath
                $failinglinenumber = $_.InvocationInfo.ScriptLineNumber
                $scriptname = $_.InvocationInfo.ScriptName

                Write-Verbose "Start writing to Error log."
                Write-ErrorLog -hostname $computer -env $env -logicalname $logicalname -errormsg $errormsg -exception $exception -scriptname $scriptname -failinglinenumber $failinglinenumber -failingline $failingline -pscommandpath $pscommandpath -positionmsg $pscommandpath -stacktrace $stacktrace
                Write-Verbose "Finish writing to Error log."
            }
        }
    }

}
END {
}
}
#region Execution examples
#List only printers with errors
#Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

#List only offline printers
#Get-Printers -filename "OKFINservers.txt" -status "Offline" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

#List all printers
#Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

#Get-Printers -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Select-Object 'Environment', 'Logical name', 'Server name', 'Name', 'Location', 'Job count since last reset', 'Status', 'Printer status', 'Printer state', 'Detected error state', 'Extended detected error state', 'Extended printer status', 'Port name', 'Driver name', 'Network', 'Shared', 'Share name', 'Spool enabled', 'Work offline', 'Default', 'IP', 'Collected' | Out-GridView

<#
#Test ParameterSet = ServerName
Get-Printers -client "OK" -solution "FIN"
Get-Printers -client "OK" -solution "FIN" -errorlog
Get-Printers -client "OK" -solution "FIN" -errorlog -Verbose
Get-Printers -computers 'APP100001' -client "OK" -solution "FIN" -errorlog
Get-Printers -computers 'APP100001', 'APP100002' -client "OK" -solution "FIN" -errorlog -Verbose
Get-Printers -hosts 'APP100001' -client "OK" -solution "FIN" -errorlog
Get-Printers -computers (Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" )) -client "OK" -solution "FIN" -errorlog -Verbose

#Pipeline examples
'APP100001' | Get-Printers -client "OK" -solution "FIN" -errorlog
'APP100001', 'APP100002' | Get-Printers -client "OK" -solution "FIN" -errorlog -Verbose
'APP100001', 'APP100002' | Select-Object @{label="computers";expression={$_}} | Get-Printers -client "OK" -solution "FIN" -errorlog
Get-Content( "$home\Documents\WindowsPowerShell\Modules\01servers\OKFINservers.txt" ) | Get-Printers -client "OK" -solution "FIN" -errorlog -Verbose
'ERROR' | Get-Printers -client "OK" -solution "FIN" -errorlog

#Test CmdLet help
Help Get-Printers -Full

#SaveToExcel
Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -errorlog -ExcelFileName "Get-Printers" -title "Get printers info of servers in Financial solution for " -author "DJ PowerScript" -WorkSheetName "Printer Info" -client "OK" -solution "FIN" 
#SaveToExcel and send email
Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose | Save-ToExcel -sendemail -errorlog -ExcelFileName "Get-Printers" -title "Get printers info of servers in Financial solution for " -author "DJ PowerScript" -WorkSheetName "Printer Info" -client "OK" -solution "FIN" 

#Benchmark
#Time = 122 sec; Total Items = 1118
Measure-BenchmarksCmdLet { Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" -Verbose }
#Time = 117 sec; Total Items = 1118
Measure-BenchmarksCmdLet { Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" }

#Baseline create
Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Save-Baseline -errorlog -BaselineFileName "Get-Printers" -client "OK" -solution "FIN" -Verbose
#Baseline archive and create new
Get-Printers -filename "OKFINservers.txt" -status "All" -errorlog -client "OK" -solution "FIN" -Verbose | Save-Baseline -archive -errorlog -BaselineFileName "Get-Printers"  -client "OK" -solution "FIN" -Verbose

#Test ParameterSet = FileName
Get-Printers -filename "OKFINservers.txt" -errorlog -client "OK" -solution "FIN" -Verbose
Get-Printers -filename "OKFINserverss.txt" -errorlog -client "OK" -solution "FIN" -Verbose
#>
#endregion 

About Dejan Mladenović

Hey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals!
I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials
About Me...

My Posts | Website

Dejan Mladenović

Hey Everyone! I hope that this article you read today has taken you from a place of frustration to a place of joy coding! Please let me know of anything you need for Windows PowerShell in the comments below that can help you achieve your goals! I have 18+ years of experience in IT and you can check my Microsoft credentials. Transcript ID: 750479 and Access Code: DejanMladenovic
Credentials About Me...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Recent Content