📜 ⬆️ ⬇️

Auto-clean and reload print server print service

A short but useful script for admins. There is a printer server with 34 printers, and it is stuck in the print queue, usually it happens when a department printer is sent in for repair, and the other department wants them to send a document to a non-existing printer. CPU load rises and can reach 100%.

Having received such a situation several times, and finding that the print server can stand with a processor load of 30-50% a week (!) Until the admin sees it. In order to solve this problem and unload the staff, a small script was drafted, it is extremely simple and it has many analogs, I decided to post it here because it proved its usefulness again and again.


')
We have broken three printers in a row, we removed them for repair, and users of other departments continued to send jobs to the queue, as a result, auto cleaning and overloading of the print service saved us from work at that moment when we were busy repairing physical equipment.

In order to remove the load from the processor, you need to clear the print jobs in the C: \ Windows \ System32 \ spool \ PRINTERS \ directory. All files in the directory are simply deleted when the service is stopped:

Get-Service *spool* | Stop-Service -Force -Verbose Start-Sleep -Seconds 5 $path = "C:\Windows\System32\spool\PRINTERS\" Get-ChildItem $path -File | Remove-Item -Force -Verbose Get-Service Spooler | Start-Service -Verbose 

For administrative notification, we first save - who, what document, what size and where it was printed. At the same time an example of how to create objects.

 #            $temp = Get-Printer | Get-PrintJob #     $Jobs = @() #          foreach ( $p in $temp ) { #    [ordered]      #         #      ,      #        -      #           html  $props = [ordered]@{ ID = $p.Id PrinterName = $p.PrinterName UserName = $p.UserName DocumentName = $p.DocumentName DataType = $p.Datatype SubmittedTime = $p.SubmittedTime Size = $p.Size JobTime = $p.JobTime PagesPrinted = $p.PagesPrinted TotalPages = $p.TotalPages Status = $p.Status } #        $props $obj = New-Object -TypeName PSObject -Property $props #     $Jobs += $obj } #      $Jobs 

When working, it is desirable to create objects.


We want to have diagnostic information at the time of the spooler reload for this purpose, we will add a list of processes with loading on the processor and memory:

 #    $temp = Get-Process | sort -Property cpu -Descending #     $proc = @() foreach ( $p in $temp ) { #     $props = [ordered]@{ Name=$p.ProcessName CPU_total_in_seconds=$p.CPU PhysicallMemory_in_Mb=$p.WS/1mb ProcessID=$p.Id } #     $obj = New-Object -TypeName PSObject -Property $props #      $proc += $obj } $proc 

To make a decision that it is time to overload the spooler, the counts are taken from the processor and if they exceed the threshold within 5 seconds, it is considered that it is time to reload. This scheme is not optimal, for example, when installing updates, such a load may be kept, but for operational work and daily activities it proved to be sufficient, therefore, I leave it as it is:

 #  ,     95   $cfi = 0 for( $i=1; $i -le 5; $i++ ) { Start-Sleep -Seconds 1 #    $load = Get-WmiObject win32_Processor | select -Property LoadPercentage Write-Host "CPU load $load" -ForegroundColor Green if ($($load.LoadPercentage) -gt 95) { $cfi = $cfi + 1 Write-Host "indicator is $cfi" -ForegroundColor Green } } 

The script must be added to the scheduler to run every 5-10 minutes.

We use the method described here with a few changes to send a letter.

Sending mail is a separate function, because it is used in other places, you need to change the address of the mail server 'SMTPServer' = 'Exchange.domain.ru' to your server in this place:

 $params = @{'To'=$MailAddress 'From'='bot@domain.local' 'Subject'="$Subject $Date" 'Body'=$MailBody 'BodyAsHTML'=$True 'SMTPServer'='Exchange.domain.ru' } Send-MailMessage @params -Encoding $encoding 

And replace the address admin@domain.ru with the address to which the administrative notification should go here:

 Send-ToAdmin -MailAddress 'admin@domain.ru' -Style $Style -Subject '  -    100%' -Body $Body -Header1 $header 

In the original edition of the script was able to extract the DLL loaded into memory for each process in order to catch the "buggy" driver. This edition is removed because generates too much info, was implemented via ListDll , but generated a very large list.

Full script code:

 <#   ,           #> $StyleYellowSimple = @' <style> body { background-color:#ffffff; font-family:Tahoma; font-size:12pt; } td, th { border:1px solid black; border-collapse:collapse; } th { color:white; background-color:black; } table, tr, td, th { padding: 2px; margin: 0px } table { font-family: "Lucida Sans Unicode", "Lucida Grande", Sans-Serif; font-size: 14px; border-radius: 10px; border-spacing: 0; text-align: center; } th { background: #BCEBDD; color: white; text-shadow: 0 1px 1px #2D2020; padding: 10px 20px; } th, td { border-style: solid; border-width: 0 1px 1px 0; border-color: white; } th:first-child, td:first-child { text-align: left; } th:first-child { border-top-left-radius: 10px; } th:last-child { border-top-right-radius: 10px; border-right: none; } td { padding: 10px 20px; background: #F8E391; } tr:last-child td:first-child { border-radius: 0 0 0 10px; } tr:last-child td:last-child { border-radius: 0 0 10px 0; } tr td:last-child { border-right: none; } </style> '@ <#       .       #> function Send-ToAdmin { Param ( [string]$MailAddress = 'admin@domain.ru', [string]$Subject = 'Test message', [string]$Header1, [string]$Body, [string]$Style ) BEGIN {} PROCESS { Write-Verbose 'definiting CSS' <# Switch ($Style) { 'YellowSimple' { $head = $StyleYellowSimple; break } 'BlueSimple' { $head = $StyleBlueSimple; break } 'DataTable' {$head = $StyleResposTable; break } default { $head = $StyleYellowSimple; break } }#> $head = $StyleYellowSimple $encoding = [System.Text.Encoding]::UTF8 $Date = Get-Date $MailBody = ConvertTo-HTML -head $head -PostContent $Body -PreContent "<h1>$Subject. Date:$Date</h1><br><h3>$Header1</h3>" | Out-String Write-Verbose "Sending e-mail. Address: $MailAddress" $params = @{'To'=$MailAddress 'From'='bot@domain.local' 'Subject'="$Subject $Date" 'Body'=$MailBody 'BodyAsHTML'=$True 'SMTPServer'='Exchange.domain.ru' } Send-MailMessage @params -Encoding $encoding } END{} } $cfi = 0 for( $i=1; $i -le 5; $i++ ) { Start-Sleep -Seconds 1 $load = Get-WmiObject win32_Processor | select -Property LoadPercentage Write-Host "CPU load $load" -ForegroundColor Green if ($($load.LoadPercentage) -gt 95) { $cfi = $cfi + 1 Write-Host "indicator is $cfi" -ForegroundColor Green } } if ($cfi -gt 2) { #     $temp = Get-Process | sort -Property cpu -Descending $proc = @() foreach ( $p in $temp ) { $props = [ordered]@{ Name=$p.ProcessName CPU_total_in_seconds=$p.CPU PhysicallMemory_in_Mb=$p.WS/1mb ProcessID=$p.Id } $obj = New-Object -TypeName PSObject -Property $props $proc += $obj } $temp = Get-Printer | Get-PrintJob $Jobs = @() foreach ( $p in $temp ) { $props = [ordered]@{ ID = $p.Id PrinterName=$p.PrinterName UserName=$p.UserName DocumentName=$p.DocumentName DataType=$p.Datatype SubmittedTime=$p.SubmittedTime Size=$p.Size JobTime=$p.JobTime PagesPrinted=$p.PagesPrinted TotalPages=$p.TotalPages Status=$p.Status } $obj = New-Object -TypeName PSObject -Property $props $Jobs += $obj } #    Write-Host " " -ForegroundColor Green Get-Service *spool* | Stop-Service -Force -Verbose Start-Sleep -Seconds 5 $path = "C:\Windows\System32\spool\PRINTERS\" Get-ChildItem $path -File | Remove-Item -Force -Verbose Get-Service Spooler | Start-Service -Verbose $frag1 = $proc | ConvertTo-Html -As table -Fragment -PreContent '<h2>     </h2>' | Out-String $frag2 = $Jobs | ConvertTo-Html -As table -Fragment -PreContent '<h2>      </h2><br>        ( )' | Out-String $Body = '<br><br>    ..     <br><br>' $Body = $Body + $frag2 + '<br><br>' $Body = $Body + $frag1 + '<br><br>---------------------------------------------------------------------------<br>  <br><H2>          </H2>' $Date = Get-Date $header = "$Date  " $Style = 'YellowSimple' Send-ToAdmin -MailAddress 'admin@domain.ru' -Style $Style -Subject '  -    100%' -Body $Body -Header1 $header } 

The script must be added to the scheduler to run every 5-10 minutes.

Link to alternative script

Source: https://habr.com/ru/post/349490/


All Articles