Here’s a quick PowerShell script I put together to delete all print jobs from our Windows Server 2008 R2 print server. It’s run overnight as a scheduled task. We do this because sometimes our print accounting software doesn’t clear out old jobs if users haven’t released them at the printer.
EDIT: January 2015
Just reviewing my old posts. Here’s how I’d do this nowadays:
Get-WmiObject Win32_Printer -Filter "(Local = $true) and (Shared = $true)" | ForEach-Object {$_.CancelAllJobs()}
It’s better practice to do the filtering in WMI earlier, rather than retrieve more printers and filter them out in PowerShell afterwards.
Here’s the old code
$printers = Get-WmiObject Win32_Printer if ($printers.Count -eq 0) { Write-Host -ForegroundColor red "No Printers Found" exit } foreach ($printer in $printers) { if ($printer.Local -and $printer.Shared) { Write-Host -ForegroundColor Green "Cancelling all jobs on: $($printer.Name)" $printer.CancelAllJobs() } }
It will only clear print jobs on local printers that are shared out. There’s some more info about the Win32_Printer class and the CancelAllJobs method on MSDN.
Note that I haven’t included any error-checking in this script at all, so run it manually first to see if it will work. As always, run at your own risk.
To schedule it, simply create a new scheduled task:
- Run with highest privileges
- Run whether user is logged on or not
- Do not store password
- Action: Start a program: C:WindowsSystem32WindowsPowerShellv1.0powershell.exe
- Arguments: -File “C:path-to-script-filename-of-script-file.ps1”
Your script can be more efficient by using a WMI filter. Now, you are getting every printer and later going through to take an action on printers that are local and shared. The best practice is to filter as early in your expression as you can. Here’s a one line alternative.
get-wmiobject win32_printer -filter “Local=’True’AND shared=’True'” | foreach {
Write-Host “Cancelling all jobs on $($_.Name)” -ForegroundColor Green
$_.CancelAllJobs()
}
The tricky thing is that WMI filters use the legacy operators, not PowerShell operators.
LikeLike
Excellent. Goes to show why you’re an MVP… 😉
This is my second attempt at a PS script that does anything useful. I’m still getting my head around the way things operate in PowerShell. All of the different operators, the way to refer to objects inside a loop, etc.
I’ll certainly use the WMI filters if I do any similar scripting in the future. For now though, I’m happy to leave it as-is. I don’t need to worry too much about the efficiency of the script. It would be another story if I was running it on a server with 1000 printers.
Thanks for leaving feedback.
Daniel
LikeLike
I just tested your one-line edit on a Windows 7 PC and it did not delete a single print job. I created a number of print jobs to various printers on the test PC, used prnjobs.vbs -l to list all the print jobs to verify they were still sitting in various queues and waiting.
It did not work. I removed the filter and then it deleted all but one print job – but that print job did show status “Job is being deleted”.
Any reason for the difference? Maybe because it’s Windows 7 versus Windows Server 2008?
LikeLike
Hi,
I don’t have access to any Windows 7 machines on which to test this.
Daniel
LikeLike
Hi… this could be done simply with this command:
(gwmi Win32_Printer -Filter “(Local = $true) and (Shared = $true)”).CancelAllJobs()
You don’t need the Foreach-Object could also have be shortened to %
this command would also work
gwmi Win32_Printer -Filter “(Local = $true) and (Shared = $true)” | % {$_.CancelAllJobs()}
LikeLike
Yep, for sure. I wrote this early on in my PowerShell learning experience back in 2011.
LikeLike