Printer Management Using PowerShell

*******Disclaimer.  This posting contains scripting samples.  These are
provided as-is with no guaranties or warranties of any kind.  They are
not thoroughly tested in all scenarios.

Over the years, the Printing team has released a number of management technologies designed to help print administrators get their jobs done. While the Print Management Console (PMC) is the tool of choice for many, sometimes you need a scripted solution. This is where PowerShell comes in.

One of the beautiful things about PowerShell is that it provides a single entry point to a wide array of scripting tools. For instance, you can manage WMI objects, .NET objects, call console apps like SetPrinter.exe and even (if you’re adventurous) marshal native API calls through .NET to PowerShell. For the purposes of this post, though, I’m going to keep things planted firmly in what you can do using the objects provided in .NET 3.0+.

One common administrative scenario would be setting all of the print queues on a print server to print double sided or duplexed. We could do this in the PMC, but we would need to edit each queue one-by-one: not fun. Fortunately, the Print Schema (introduced in Windows Vista) provides a common syntax that we can script against, and .NET provides a number of convenient objects to represent some of the common keywords.

Let’s go to the code. First, we need to change our threading model so that everything plays nice. Then we get into the real work of importing the correct namespace (System.Printing) and set up some objects we’ll be using. Note that we're filtering the queues we get back from the (local) server using a flag from System.Printing.EnumeratedPrintQueueTypes so that we only get shared queues. You could add more flags into the array we pass to GetPrintQueues() as well.

 $host.Runspace.ThreadOptions = "ReuseThread"
Add-Type -AssemblyName System.Printing
$permissions = [System.Printing.PrintSystemDesiredAccess]::AdministrateServer
$queueperms = [System.Printing.PrintSystemDesiredAccess]::AdministratePrinter
$server = new-object System.Printing.PrintServer -argumentList $permissions
$queues = $server.GetPrintQueues(@([System.Printing.EnumeratedPrintQueueTypes]::Shared))

Now that we have a collection of PrintQueue objects in $queues, we can iterate over them in a foreach loop. The first challenge we’ll need to deal with is getting a PrintQueue object where we have administrative privileges. Note: You will most likely have to run PowerShell as an administrator in order to get permission to modify the PrintQueue object.

 foreach ($q in $queues) { 
    #Get edit Permissions on the Queue
    $q2 = new-object System.Printing.PrintQueue -argumentList $server,$q.Name,1,$queueperms
}

From here it is just a matter of finding devices that support the desired PrintCapability and then setting it to the desired value. We'll be using the DuplexingCapability object in this example.

  $duplexCaps = $q2.GetPrintCapabilities().DuplexingCapability
    if ($duplexCaps.Contains([System.Printing.Duplexing]::TwoSidedLongEdge)) {
      $q2.DefaultPrintTicket.Duplexing = [System.Printing.Duplexing]::TwoSidedLongEdge
        $q2.commit()
    }

Putting it all together:

 $host.Runspace.ThreadOptions = "ReuseThread"
Add-Type -AssemblyName System.Printing
$permissions = [System.Printing.PrintSystemDesiredAccess]::AdministrateServer
$queueperms = [System.Printing.PrintSystemDesiredAccess]::AdministratePrinter
$server = new-object System.Printing.PrintServer -argumentList $permissions
$queues = $server.GetPrintQueues(@([System.Printing.EnumeratedPrintQueueTypes]::Shared))


foreach ($q in $queues) { 
    #Get edit Permissions on the Queue
    $q2 = new-object System.Printing.PrintQueue -argumentList $server,$q.Name,1,$queueperms
    
    #Set DefaultPrintTicket
    $duplexCaps = $q2.GetPrintCapabilities().DuplexingCapability
    if ($duplexCaps.Contains([System.Printing.Duplexing]::TwoSidedLongEdge)) {
        $q2.DefaultPrintTicket.Duplexing = [System.Printing.Duplexing]::TwoSidedLongEdge
       $q2.commit()
    }
}

This is of course, just one example of what you could do now that you've got the System.Printing namespace mapped into PowerShell.

Thanks,

Justin Hutchings & Alan Morris

Windows-Printing