May 21st, 2009

Hey, Scripting Guy! How Can I Perform More Than One Action with the Win32_Printer WMI Class?

Hey, Scripting Guy! Question

Hey, Scripting Guy! The Win32_Printer WMI class has several methods that are listed in it. But I am not sure how to best use these methods from inside a Windows PowerShell script. I do not want to create four different scripts to send a test page, clean out print jobs, and to cycle the print queue. Do you have an example of how I might do more than one action in a script?

– AA

SpacerHey, Scripting Guy! Answer

Hi AA,

Ed is relaxing after a long hard week of working at Tech∙Ed. His talk was a success, and he is resting on his laurels. He feels that he might be able to milk it for at least another week. In fact, he is sitting with his feet propped up listening to Mac Davis on his Zune. Mac Davis, he feels, goes well with green tea with a hint of jasmine. If we can get his attention, perhaps he might return to work.

This week we will examine printing. There are lots of resources related to printing on the TechNet Script Center. There is a collection of Hey, Scripting Guy! articles that lists 24 articles relates to both server-side and client-side printing. We have almost 50 scripts in the printer section of the Script Center Script Repository. There are also almost 50 scripts in the printer section of the Community-Submitted Scripts Center. We have some good technical information about printing in the Scripting Guide. All those resources are in VBScript. To use them in Windows PowerShell, you would have to translate the scripts into PowerShell. The Microsoft Press book, Windows PowerShell Scripting Guide, has a whole chapter devoted to printing.

Well, AA, you are in luck, we have Ed’s attention. Ed loves writing scripts that perform multiple actions. To do this, he uses command-line parameters. The ManagePrinter.ps1 script shows how to call multiple printer functions. You can call it by using command lines similar to this. Each command line allows you to access a different functionality provided by the ManagePrinter.ps1 script. The five different combinations allow you to perform routine tasks such as sending a test page, stopping print jobs, pausing, and resuming the printer.

# List local printers on the localhost.\ManagePrinter.ps1 -list -computer localhost# Send a test page to a printer named testprinter on the localhost .\ManagePrinter.ps1 -computer localhost -sendTestPage -printerPath testprinter# Cancel all print jobs on the testprinter on the localhost.\ManagePrinter.ps1 -computer localhost -stopPrintJobs -printerPath testprinter# Resume printing on the testprinter on the localhost.\ManagePrinter.ps1 -computer localhost -printerPath testprinter –resume# suspend printing on the testprinter on the localhost.\ManagePrinter.ps1 -computer localhost -printerPath testprinter –suspend

The complete ManagePrinter.ps1 script is seen here:

ManagePrinter.ps1

Param(            $computer,             $printerPath,             [switch]$list,             [switch]$sendTestPage,            [switch]$stopPrintJobs,            [switch]$suspend,            [switch]$resume)Function Get-Printer($computer){ Get-WmiObject -class Win32_Printer -computer $computer} #end Get-PrinterFunction Format-Printer($printObject){ Write-Host -foregroundcolor cyan "Shared printers on $computer" $printObject |  Where-Object { $_.sharename } | Format-Table -property sharename, location, comment -autosize -wrap} #end Format-PrinterFunction Get-SuccessCode($code){ if($code.ReturnValue -eq 0)  { Write-Host -foregroundcolor green "Operation suceeded!" } Else  { Write-Host -foregroundcolor red "Operation failed with $($code.returnvalue)" }} #end get-successcodeFunction Send-TestPage($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Sending test page to $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.PrintTestPage()} #end Send-TestPageFunction Stop-AllPrintJobs($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Cancelling all print jobs on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.CancelAllJobs()} #end Stop-AllPrintJobsFunction Suspend-Printer($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Suspending printing on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.Pause()} #end Suspend-PrinterFunction Resume-Printer($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Resuming printing on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.Resume()} #end Resume-Printer# *** Entry Point to Script ***if($list) { Format-Printer(Get-Printer($computer)) ; exit }if($sendTestPage) {   Get-SuccessCode -code `   (Send-TestPage -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit }if($stopPrintJobs) {   Get-SuccessCode -code `   (Stop-AllPrintJobs -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit }if($suspend) {   Get-SuccessCode -code `   (Suspend-Printer -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit }if($resume) {   Get-SuccessCode -code `   (Resume-Printer -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit }

The first thing the ManagePrinter.ps1 script does is create a number of parameters. The –computer parameter holds the name of the destination computer, and the –printerpath parameter holds the name of the printer. The other parameters are switched parameters that are used to obtain access to different functions within the script. The param statement is seen here:

Param(            $computer,             $printerPath,             [switch]$list,             [switch]$sendTestPage,            [switch]$stopPrintJobs,            [switch]$suspend,            [switch]$resume)

The first function, the Get-Printer function, is the same as the Get-Printer function from Tuesday’s article:

Function Get-Printer($computer){Get-WmiObject -class Win32_Printer -computer $computer} #end Get-Printer

The second function, the Format-Printer function, is also the same as the Format-Printer function from Tuesday’s article:

Function Format-Printer($printObject){Write-Host -foregroundcolor cyan "Shared printers on $computer"$printObject | Where-Object { $_.sharename } |Format-Table -property sharename, location, comment -autosize -wrap} #end Format-Printer

We now come to the Get-SuccessCode function. Guess what? It is also the same as the Get-SuccessCode function from Tuesday (please refer to Tuesday’s “Hey, Scripting Guy!” article for a discussion of that function):

Function Get-SuccessCode($code){if($code.ReturnValue -eq 0)  { Write-Host -foregroundcolor green "Operation suceeded!" }Else  { Write-Host -foregroundcolor red "Operation failed with $($code.returnvalue)" }} #end get-successcode

Now we arrive at something new. The Send-TestPage function is used to send a test page to a printer. When this function is called, it is passed a WMI Win32_Printer object (which is returned by the Get-Printer function) in addition to the name of the printer that will receive the test page. The first thing the Send-TestPage function does is display a message that states it is sending a test page to the printer designated by the string contained in the $printerPath variable. The WMI Win32_Printer object is pipelined to the Where-Object cmdlet. Inside the script block for the Where-Object, the deviceID property of each printer in the collection of printers is searched to see whether it matches the string contained in the $printerPath variable. If a match is found, the printer object is held in the $dp variable. The PrintTestPage method is called from the Win32_Printer WMI object that is stored in the $dp variable. The complete Send-TestPage function is shown here:

Function Send-TestPage($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Sending test page to $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.PrintTestPage()} #end Send-TestPage

The command line to send a test page to a printer specifies the name of the computer, the sendtestpage switched parameter, and the name of the printer. This is seen here:

.\ManagePrinter.ps1 -computer localhost -sendTestPage -printerPath testprinter

When the ManagePrinter.ps1 script starts with the previous command line, this is displayed:

Image of a successful operation

 

If the ManagePrinter.ps1 script is run with the StopPrintJobs parameter, it calls the Stop-AllPrintJobs function. The command line to call the Stop-AllPrintJobs function is seen here:

.\ManagePrinter.ps1 -computer localhost -stopprintjobs -printerPath testprinter

When the Stop-AllPrintJobs function is called, it receives the Win32_Printer object that is contained in the $printObject variable and the path of the printer whose print jobs are to be canceled. The syntax of the Stop-AllPrintJobs function resembles the SendTestPage function except that the Stop-AllPrintJobs function calls the CancelAllJobs method from the Win32_Printer object that is contained in the $dp variable. The Stop-AllPrintJobs function is seen here:

Function Stop-AllPrintJobs($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Canceling all print jobs on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.CancelAllJobs()} #end Stop-AllPrintJobs

If you have to suspend printing, you call the Suspend-Printer function and pass the Win32_Printer object and the path to the printer that will be paused. When you start the ManagePrinter.ps1 script to pause printing, you would use this command-line syntax:

.\ManagePrinter.ps1 -computer localhost -printerPath testprinter –suspend

In the Suspend-Printer function, the first thing that happens is a message is displayed that states printing is being suspended on the target printer. The Win32_Printer WMI object is pipelined to the Where-Object where it is filtered based on the deviceID property. The resulting object is used to call the pause method. This is seen here:

Function Suspend-Printer($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Suspending printing on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath }  $dp.Pause()} #end Suspend-Printer

When the ManagePrinter.ps1 script is used to suspend printing, the target printer’s status changes to paused:

Image of the target printer's status that has changed to Paused

 

To resume printing, you call the Resume-Printer function. This function works the same as the Suspend-Printer function because it accepts two parameters. The first parameter is the Win32_Printer object that is contained in the $printObject variable, and the other is the name of the printer stored in the $printerPath variable. The resume method is called from the printer object. To resume printing by using the ManagePrinter.ps1 script, you would use this command line:

.\ManagePrinter.ps1 -computer localhost -printerPath testprinter –resume

The complete Resume-Printer function is seen here:

Function Resume-Printer($printObject, [string]$printerPath){  Write-Host -foregroundcolor cyan "Resuming printing on $printerPath"  $dp = $printObject |  Where-Object { $_.deviceID -match $printerPath } $dp.Resume()} #end Resume-Printer

The entry point to the script is used to examine the command line parameters. If the –list parameter is specified, the Get-Printer function is called by using the computer name that is contained in the $computer variable. The resulting management object is passed to the Format-Printer function and the script exits. This is seen here:

if($list) { Format-Printer(Get-Printer($computer)) ; exit }

If the –sendTestPage switched parameter is used on the command line, the Get-Printer function is called and the resulting management object is passed to the Send-TestPage function by using the –printObject parameter:

if($sendTestPage){   Get-SuccessCode -code `   (Send-TestPage -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit }

If the –stopPrintJobs switched parameter is used, the Get-Printer function is used to retrieve a Win32_Printer management object, which is passed to the Stop-AllPrintJobs function through the –printObject parameter. The target printer is passed via the –printerPath parameter. The return value from calling the Stop-AllPrintJobs function is parsed by the Get-SuccessCode function. This is seen here:

if($stopPrintJobs){   Get-SuccessCode -code `   (Stop-AllPrintJobs -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit}

If the script is run with the –suspend switched parameter, the Get-Printer function is used to return a Win32_Printer object, which is passed to the Suspend-Printer function through the –printObject parameter. The path of the printer is passed to the Suspend-Printer function through the –printerpath parameter. The return value is evaluated by the Get-SuccessCode function through the –code parameter. This is shown here:

if($suspend) {   Get-SuccessCode -code `   (Suspend-Printer -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit}

If the script is started with the –resume parameter, the first thing that happens is the Get-Printer function is used to create a Win32_Printer WMI management object, which is passed to the Resume-Printer function through the –printobject parameter. The name of the printer is passed to the Resume-Printer function through the –printerpath parameter. The Get-SuccessCode function is used to evaluate the return value. This is seen here:

if($resume){   Get-SuccessCode -code `   (Resume-Printer -printObject(Get-Printer($computer)) -printerPath $printerPath)   exit}

Well, AA, we come to the end of the ManagePrinter.ps1 script. It is also the end of Printing Week on the Script Center. Join us tomorrow for Quick-Hits Friday as we answer several short e-mail messages that cover a variety of topics. Until then, take care and we’ll see you over the weekend and next week.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Author

0 comments

Discussion are closed.