Hey, Scripting Guy! How Can I Use Windows PowerShell to Remove Old Printer Connections, List Printers, and Set New Default Printers?

Hey, Scripting Guy! How Can I Use Windows PowerShell to Remove Old Printer Connections, List Printers, and Set New Default Printers?

  • Comments 4
  • Likes

Hey, Scripting Guy! Question

Hey, Scripting Guy! Well it finally happened. Our budget request for new printers was approved. We have gotten them unboxed, distributed, and hooked up to the LAN. We have even downloaded the latest drivers from the Internet, and updated the firmware on several of the printers. The drivers are installed on the print servers, and the shares have been created. Now I have to remove the old printer connections from the client workstations, and set new default printers. Can I do this in Windows PowerShell?

- BP

SpacerHey, Scripting Guy! Answer

Hi BP,

We are absolutely swamped with the 2009 Summer Scripting Games, which are coming up I the week of June 15. We are busy rounding up guest commentators—this year we will have 40 of them! Trying to select 40 commentators from around the scripting world is a bit of a challenge, but we have rounded up a group of some of the best scripters in the world. About half of the commentators have already turned in their entries (the Games are so much fun, they could not wait to get started) and Ed was impressed—and in several cases actually astonished—by the creative approaches to some events. We absolutely guarantee that you will similarly be blown away by some of the scripts written by the guest commentators. One commentator even went so far as to…sorry, can’t reveal this yet. Cliffhanger! Okay, about your printer problem.

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.

The SetDefaultPrinterDeletePrinterConnection.ps1 script is seen here. It uses Windows PowerShell to let you list local printers, set the default printer connection, and delete locally defined printers.

SetDefaultPrinterDeletePrinterConnection.ps1

Param($computer, $printerPath, [switch]$list, [switch]$setDefault, [switch]$deletePrinter)

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

Function Format-LocalPrinter($printObject)
{
 Write-Host -foregroundcolor cyan "Local printers on $computer"
 $printObject |
 Format-Table -property deviceID, location, default, comment -autosize -wrap
} #end Format-Printer

Function Set-DefaultPrinter($printObject, [string]$printerPath)
{
 Write-Host -foregroundcolor cyan "Setting $printerPath to default printer"
 $dp = $printObject |
 Where-Object { $_.deviceID -match $printerPath }
 $dp.SetDefaultPrinter()
} #end Set-DefaultPrinter

Function Remove-Printer($printObject, [string]$printerPath)
{
 Write-Host -foregroundcolor cyan "Removing $printerPath"
  $dp = $printObject |
 Where-Object { $_.deviceID -match $printerPath }
 $dp.psbase.Delete()
}

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

# *** Entry Point to Script ***
if($list) { Format-LocalPrinter(Get-Printer($computer)) ; exit }
if($setDefault)
 {
   Get-SuccessCode -code `
   (Set-DefaultPrinter -printObject(Get-Printer($computer)) -printerPath $printerPath)
 exit
 }
If($deletePrinter)
 {
  Remove-Printer -printObject (Get-Printer($computer)) -printerPath $printerPath
  exit
 }

In the SetDefaultPrinterDeletePrinterConnection.ps1 script the first thing that you have to do is to create some command-line parameters. These command-line parameters enable you to change the way the script runs when it starts. The first parameter, –computer, is used to specify which computer to work with. The –printerpath parameter is used to specify the printer. The –list switched parameter is used to provide a list of shared printers from the computer specified by the –computer parameter. The –setDefault switched parameter will set the printer that is specified by the –printerpath parameter to the default printer. The –deletePrinter switched parameter is used to delete the printer that is named by the –printerpath parameter. These command-line parameters are shown here.

Param($computer, $printerPath, [switch]$list, [switch]$setDefault, [switch]$deletePrinter)

The first function that you come to is the Get-Printer function. This is the same function that was in yesterday's script.

It is used to create the Win32_Printer WMI management object. To do this, you use the Get-WmiObject cmdlet. This is seen here:

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

The Format-LocalPrinter function is used to format the information that is displayed about the local printer. This function is also the same as the function that was used yesterday. The Format-LocalPrinter function accepts Win32_Printer WMI management object that was created in the Get-Printer function as input. Then it uses the Format-Table cmdlet to display four properties in a table. The Format-LocalPrinter function is shown here.

Function Format-LocalPrinter($printObject)
{
Write-Host -foregroundcolor cyan "Local printers on $computer"
$printObject |
Format-Table -property deviceID, location, default, comment -autosize -wrap
} #end Format-Printer

When the SetDefaultPrinterDeletePrinterConnection.ps1 script is run with the –computer parameter and the –list switch, the Format-LocalPrinter function will be called. This command line is seen here:

PS bp:\> .\SetDefaultPrinterDeletePrinterConnection.ps1 -list -computer localhost

The resulting output from the Format-LocalPrinter function is seen in the following image.

Image of output from Format-LocalPrinter function

Next, the Set-DefaultPrinter function is created. This function is used to set the printer named in the –printerpath parameter to be the default printer on the computer. The SetdefaultPrinter method is an instance method. This means that it is available when you have a single instance of a printer. To obtain an instance of the win32_Printer WMI class, the printer object that is stored in the $printObject variable is piped to the Where-Object cmdlet. The Where-Object cmdlet is used to find an instance of a printer that has a value that is contained in the deviceID property that will match the value supplied through the –printerpath parameter. When the match is found, the instance is stored in the $dp variable. It is this instance that contains the SetDefaultPrinter WMI method. The Set-DefaultPrinter function is seen here:

Function Set-DefaultPrinter($printObject, [string]$printerPath)
{
Write-Host -foregroundcolor cyan "Setting $printerPath to default printer"
$dp = $printObject |
Where-Object { $_.deviceID -match $printerPath }
$dp.SetDefaultPrinter()
} #end Set-DefaultPrinter

The command line to set the default printer is seen here. The computername parameter, the setdefault switched parameter, and the printerpath parameters must be supplied.

PS bp:\> .\SetDefaultPrinterDeletePrinterConnection.ps1 -setDefault -printer testprinter -computer localhost

When the script is run, the output shown in the following image is displayed.

Image of script output


It is time create the function that deletes the printer. To do this, create a function named Remove-Printer and pass it the Win32_Printer WMI object that is stored in the $printobject variable and a string that represents the path of the printer to be deleted. Inside the function use the Write-Host cmdlet to display a message in cyan that indicates which printer is being removed. The Win32_Printer object that is stored in the $printobject variable is piped to the Where-Object cmdlet. Inside the script block for the Where-Object cmdlet the deviceID property is examined to find a match for the string that was supplied through the printerpath parameter. When a match is found, the resulting Win32_Printer instance is stored in the $dp variable. To delete the instance, you have to access the underlying Win32_Printer WMI object by using the psbase property. As soon as you have the underlying base WMI object, you can call the delete method. The Remove-Printer function is shown here.

Function Remove-Printer($printObject, [string]$printerPath)
{
Write-Host -foregroundcolor cyan "Removing $printerPath"
$dp = $printObject |
Where-Object { $_.deviceID -match $printerPath }
 $dp.psbase.Delete()
}

The command line used to delete a printer connection involves passing the –deleteprinter switched printer, specifying the printer to delete and the computer upon which to operate. This is shown here:

PS bp:\> .\SetDefaultPrinterDeletePrinterConnection.ps1 -delete -printer testprinter -computer localhost
Removing testprinter
PS bp:\>

Now it is time to evaluate the return code from calling the method. This is the same function that was in yesterday's script. The return code is passed through the –code parameter of the Get-SuccessCode function. If it is equal to 0, the method call succeeded. If it is equal to something, an error occurred. The Get-SuccessCode function is seen here:

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 you reach the entry point to the script. The first thing that is performed is to check for the presence of the –list switched parameter. If it is found, the Get-Printer function is called, and the resulting printer object is passed to the Format-LocalPrinter function that creates a formatted list of all local printers on the target system. The script then exits. This is seen here:

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

If the –setDefault switched parameter is called, the script calls the Get-Printer function and retrieves a printer object. This printer object is passed to the Set-DefaultPrinter function, which takes the printer referenced in the $printerPath variable and sets it to the default printer. The return code from calling the SetDefaultPrinter method is passed to the Get-SuccessCode function, which interprets the return value. The script then exits. This line of code is seen here:

if($setDefault)
{
   Get-SuccessCode -code `
   (Set-DefaultPrinter -printObject(Get-Printer($computer)) -printerPath $printerPath)
exit
}

You can also use the SetDefaultPrinterDeletePrinterConnection.ps1 script to delete a local printer connection. If the script is run with the –deletePrinter switched parameter, the script calls the Get-Printer function and creates a printer object. It passes the printer object to the Remove-Printer function, which will delete the printer that is named in the $printerPath variable. This is seen here:

If($deletePrinter)
{
  Remove-Printer -printObject (Get-Printer($computer)) -printerPath $printerPath
  exit
}

 

Well, BP, we have successfully set the default printer, deleted printer connections, and obtained a listing of local printers. Along the way, we used a couple of functions that we had created previously. Join us tomorrow as we continue with Printer Week. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Scripting guys:

    How do you get the WMI query to find network printers that have been added by users manually?  When polling remote machines I only get a list of printers that were installed as administrators.  If I query as a user locally then I get the list of all network printers that were installed as that user.

  • It is not possible to do that with WMI.

    Printers are stored in teh registry of the user. WMI does not read remote registry of users.

  • Help!  This code works when I set my default printer:

    PS H:\Powershell\scripts> .\includes\PrinterHandler.ps1 -setdefault "MITS_Ricoh" -computer localhost

    Setting MITS_Ricoh to default printer

    Operation suceeded!

    But when I try to remove I get this error:

    PS H:\Powershell\scripts> .\includes\PrinterHandler.ps1 -delete "MITS_Ricoh" -computer localhost

    Removing MITS_Ricoh

    Exception calling "Delete" with "0" argument(s): "Access denied "

    At H:\Powershell\scripts\includes\PrinterHandler.ps1:28 char:2

    +  $dp.psbase.Delete()

    +  ~~~~~~~~~~~~~~~~~~~

       + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException

       + FullyQualifiedErrorId : DotNetMethodException

    What gives?

  • the removed command in my last comment should have looked more like this:

    PrinterHandler.ps1 -delete -printer "MITS_Ricoh" -computer localhost