PLEASE READ FIRST!

I've now been blogging here since 2007! ...Wow, has it been that long already?! Over the years, I've covered a wide array of subjects from scripting, troubleshooting, to the occasional hobby project. I have literally heard from thousands of you over the years with questions or even just offering me a bit of thanks!

Recently, I quit my full-time job and started work on an IT business, Rhythm IT Solutions, helping other IT departments manage their IT environments. We're offering consulting & professional services (Office 365 Migrations, Network Discovery, Firewall Management, etc...) as well as Endpoint Management (AV, Patch Management EDR, Managed Backup, etc...)



If there is something (on my blog or not) that you could use some additional help with, I would LOVE to hear from you! Please feel free to reach out to me using the contact links here or the contact form on Rhythm's website.

For those wondering, I do plan on continuing my work on the blog. So don't worry! There are plenty of Greg Strike posts yet to come! 😊 Thanks for stopping by!

PLEASE READ FIRST!




Update 2011-07-06: Support for Windows 2008+ servers has been added as well as handling stand-alone vs. clustered servers.

If you haven’t seen it yet, check out my posting on my Group Policy VBScript to Replace, Add, Remove and Manage User Printer Queues.

Sometimes, managing a print server can be a real pain… Ok, who are we kidding? It’s a pain! Period. Printer failures, new installations or someone forgot to tell you they tossed that printer into the garbage compactor. These are all things that can add up to have printer queues hanging around that are just not being utilized any longer.

To help resolve this, I wrote a PowerShell script that audits the printer queues on a server (locally or remote) and will tell us whether or not a Printer Queue has been used and if so, when it was last used.

The script works by first grabbing a list all of the printer queues on a print server. It then goes through all the logs in the print server’s event log and looks specifically for ‘Print’ events. The key events we are looking for are the ones like below as they have the information we need, a queue name and a time. This is what it looks like on a Windows 2003 server:

"Document [number], [title] owned by [user] was printed on [printer] via port [port].  Size in bytes: [bytes]; pages printed: [pages]"

It can take a while to sort through all the events but as it does it tracks whether or not a queue has been used and when the last time it was used.

Once complete we get a nice little CSV file to look at. From there it should be pretty obvious which queues are in use or not.

Hold it! There is a caveat… isn’t there always? The script can only go back as far as the event log does. So if your servers are configured to discard old events or the System log has recently been cleared this script may not be as helpful. Either way, the script is below. Enjoy!

#  Script name:     PrinterQueueAudit.ps1
#  Created on:      2010-11-18
#  Author:          Gregory Strike
#  URL:             //www.gregorystrike.com/2010/11/18/powershell-script-to-audit-print-server-queue-usage/
#
#  Purpose:         A script used to audit Printer Queues on a server (local or remote)
#                   to determine when the queues were last used or if at all.  A CSV
#                   file (PrinterQueueAudit.csv) is then generated with the results.
#
#  Requirements:    This script requires the ability to read printer queues and the 'System'
#                   event log on the Print Server.  The script is only able to go back in
#                   time as far as the Event Log.
#
#  Updates:
#                   2011-07-06
#                   Added Windows 2008+ Support
#                   Added code to handle certain stand-alone servers.

Clear

#Set these variables manually.
#MANUAL - Change this to your Print Server name.
$Computer = "YOUR-SERVER"
#MANUAL - Is $Computer a clustered name?
$Cluster = $True

#Create a custom type (Queue) to define our queues and their usage.
Add-Type @'
public class Queue{
    public System.String Name;
    public System.Boolean Used;
    public System.DateTime LastUsed;
}
'@

Write-Host ("Processing Print Server: " + $Computer)

#Detect the Windows version
$WMIVersion = Get-WMIObject -Class Win32_OperatingSystem -Property "Version" -Computer $Computer
$Version = [UInt32]$WMIVersion.Version.SubString(0,1)
If ($Version -ge 6){
    Write-Host ("OS Version: Windows 2008 or later.")
    $Windows2008 = $True
} else {
    Write-Host ("OS Version: Windows 2003 R2 or earlier.")
    $Windows2008 = $False
}

#Get all printer queues from the server.
Write-Host "Gathering Printer Queues..."
If ($Cluster) {
    $ServerQueues = Get-WMIObject -Class Win32_PerfFormattedData_Spooler_PrintQueue -Property "Name" -Computer $Computer
} else {
    $ServerQueues = Get-WMIObject -Class Win32_Printer -Property "Name" -Computer $Computer
}

#Create an array of our custom type and populate it with our the queue names.
$Queues = @()
ForEach ($ServerQueue in $ServerQueues){
    $Queue = New-Object -typeName Queue
    If ($Cluster) {
        $SplitName = ($ServerQueue.Name.Split("\"))
        $Queue.Name = $SplitName[$SplitName.Count - 1]
    } else {
        $Queue.Name = $ServerQueue.Name
    }

    $Queue.Used = $False
    $Queues = $Queues + $Queue
}

Write-Host "Gathering Event Log Data from Event Log.  This may take a while... "
#Get all Events from the  Event Log of the Computer.

If ($Windows2008) {
    $Events = (Get-WinEvent Microsoft-Windows-PrintService/Operational -Computer $Computer)
	} else {
    $Events = (Get-EventLog -LogName "System" -Computer $Computer)
}

$NumEvents = $Events.Count
Write-Host ("...There are " + $NumEvents + " records.")

#Loop through ALL events and only process "Print" events.
Write-Host("Processing Print Events...")
For ($Index = ($Events.Count - 1); $Index -ge 0; $Index--){
    $PercentComplete = (100 - [Math]::Round( ($Index / ($NumEvents - 1) * 100), 0))
    If ($PercentComplete -ne $LastPercentComplete){
        #Outputs the percentage... This looks good in the PowerShell console, not so much in ISE.
        Write-Host([System.String]::Format("`b`b`b`b`b`b`b`b`b`b`b`b`b`b{0:000}% complete.", $PercentComplete)) -NoNewLine
        $LastPercentComplete = $PercentComplete
    }

    $Log = $Events[$Index]

    #Check if the event was a print job event.
    If ($Log.Message.Contains(" was printed on ")){

        #Strip message to get just the printer name
        If ($Windows2008) {
            $Step1 = $Log.Message.SubString(0, $Log.Message.IndexOf(" through port "))
        } else {
            $Step1 = $Log.Message.SubString(0, $Log.Message.IndexOf(" via port "))
        }

        $Printer = $Step1.SubString($Step1.IndexOf(" was printed on ") + 16)        

        #Find queue name in our array and update with results.
        ForEach($Queue in $Queues){
            If ($Queue.Name -eq $Printer){
                $Queue.Used = $True

                #Only save time if it is more recent.
                If ($Windows2008) {
                    If ($Log.TimeCreated -gt $Queue.LastUsed){
                        $Queue.LastUsed = $Log.TimeCreated
                    }
                } else {
                    If ($Log.TimeGenerated -gt $Queue.LastUsed){
                        $Queue.LastUsed = $Log.TimeGenerated
                    }
                }

            }
        }
    }
}

Write-Host("")
Write-Host("Exporting results to PrinterQueueAudit.csv...")
$Queues | Export-CSV PrinterQueueAudit.csv


PLEASE READ FIRST!

I've now been blogging here since 2007! ...Wow, has it been that long already?! Over the years, I've covered a wide array of subjects from scripting, troubleshooting, to the occasional hobby project. I have literally heard from thousands of you over the years with questions or even just offering me a bit of thanks!

Recently, I quit my full-time job and started work on an IT business, Rhythm IT Solutions, helping other IT departments manage their IT environments. We're offering consulting & professional services (Office 365 Migrations, Network Discovery, Firewall Management, etc...) as well as Endpoint Management (AV, Patch Management EDR, Managed Backup, etc...)



If there is something (on my blog or not) that you could use some additional help with, I would LOVE to hear from you! Please feel free to reach out to me using the contact links here or the contact form on Rhythm's website.

For those wondering, I do plan on continuing my work on the blog. So don't worry! There are plenty of Greg Strike posts yet to come! 😊 Thanks for stopping by!

PLEASE READ FIRST!





Gregory Strike

Husband, father, IT dude & blogger wrapped up into one good looking package.