Get-PrintJobs.ps1 PowerShell script

After a recent upgrade of our print servers, I discovered that the Print Spooler service event logging had been enhanced, and changed enough that some PowerShell reporting scripts that worked just fine on Windows Server 2008 (32-bit) no longer worked on Server 2012 R2.

To get the reports working again, I had to enable the Microsoft-Windows-PrintService/Operational log. I also had to increase the log size from the default in order to retain more than one day’s events. The trickiest part was figuring out the XPath query syntax for retrieving events from a particular printer. The newer syntax makes more sense to me, but it took me a long time to arrive at it.

Following Don Jones‘ entreaty to build tools and controllers, I offer this tool script, which retrieves (simplified) print job events, and cares not a whit about formatting or saving.


<#
.SYNOPSIS
Gets successful print job events and returns simplified objects with relevant
details.

.DESCRIPTION
Collects the successful print jobs from the PrintService Operational log, with
optional query parameters including Printer name and start and end times.

.PARAMETER PrinterName
The share name of the printer for which events will be retrieved.

.PARAMETER StartTime
The beginning of the interval during which events will be retrieved.

.PARAMETER EndTime
The end of the interval during which events will be retrieved.

.EXAMPLE
C:\> Get-PrintJobs.ps1
Returns objects representing all the successful print jobs (events with id 307).

.EXAMPLE
C:\> Get-PrintJobs.ps1 -PrinterName 'Accounting HP LaserJet'
Returns objects for all the jobs on the Accounting printer.

.EXAMPLE
C:\> Get-PrintJobs.ps1 -PrinterName 'Accounting HP LaserJet' -StartTime (Get-Date).AddHours(-12)
Returns objects for all the jobs on the Accounting printer generated in the last twelve hours.
.NOTES
Script Name: Get-PrintJobs.ps1
Author : Geoff Duke <Geoffrey.Duke@uvm.edu>

Edit 2014-10-08: Generalizing from dept printer report script, fixing XPath
query syntax.

Edit 2012-11-29: Job is run as SYSTEM, and computer object has been granted
Modify rights to the destination directory.
#>

Param(
[string] $PrinterName,

[datetime] $StartTime,

[datetime] $EndTime
)
Set-StrictMode -version latest
# Building XPath query to select the right events
$filter_start = @'
<QueryList>
  <Query Id="0" Path="Microsoft-Windows-PrintService/Operational">
    <Select Path="Microsoft-Windows-PrintService/Operational">
'@

$filter_end = @'
    </Select>
  </Query>
</QueryList>
'@

$filter_match = '*[System[(EventID=307)' #need to add ']]' to close

if ( $StartTime -or $EndTime) {
    $filter_match += ' and TimeCreated[' #need to add ']' to close
    $time_conds = @()

    if ( $StartTime ) {
        $time_conds += ( '@SystemTime&gt;=' +
            "'{0:yyyy-MM-ddTHH:mm:ss.000Z}'" -f $StartTime.ToUniversalTime()
        )
    }
    if ( $EndTime ) {
        $time_conds += ( '@SystemTime&lt;=' +
            "'{0:yyyy-MM-ddTHH:mm:ss.000Z}'" -f $EndTime.ToUniversalTime()
        )
    }

    $filter_match += ( $time_conds -join ' and ' ) + ' ]' # Closing TimeCreated[
}

$filter_match += "]]`n" # Closing [System[

if ( $PrinterName ) {
    $filter_match += @"
  and
*[UserData[DocumentPrinted[(Param5='$PrinterName')]]]
"@
}

write-debug "Using Filter:`n $filter_match"

# The $filter variable below is cast as XML, that's getting munged
# by WordPress or the SyntaxHighlighter as '1'
 $filter = ($filter_start + $filter_match + $filter_end)

get-winevent -filterXML $filter | foreach {
    $Properties = @{
        'Time' = $_.TimeCreated;
        'Printer' = $_.Properties[4].value;
        'ClientIP' = $_.properties[3].value.SubString(2);
        'User' = $_.properties[2].value;
        'Pages' = [int] $_.properties[7].value;
        'Size' = [int] $_.properties[6].value
    }

    New-Object PsObject -Property $Properties
}

If you find this script useful, please let me know. If you find any bugs, definitely let me know!

Leave a Reply