1. december 2011

Dirty Printer solution

Greetings!!

I dont know about you, but we have had some HUGE proplems with HP printers and its universal drivers the last year.  Administering some 500+ HP Printers this means ALOT of time spend on trouble shooting and fixing problems.

The latest issue is the some printers suddently use Raster graphics instead of Vector graphics which means that the time it takes to print a document increases from a few seconds to several minutes, plus a 100kb document infaltes to a 1gb document!!

Unfortunatly this setting is being set into a registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\SY101P01\Default Devmode.  This registry key contains several settings and is unique for each printer.  It is not an option to hardcode anything into this key in this scenario.

I found that when a printer gets the raster setting, the registry key contains the following sequence:  "82 65 83 84 69 82 77 79 68 69".
I saw no other option to make a backup of det default Devmode for each printer when it was in a good condition. 

The following script checks if a printer graphics mode is Raster and if it is the replace the dirty regkey with a healty one.


Function SetDevModeToVector($printer,$printerRegKey)
{
 if(Test-Path ("c:\Mandatory\Print\devmode\$printer"+".txt"))
 {
   Write-Host "Restoring Registry"
   $strdevMode=Get-Content ("c:\Mandatory\Print\devmode\$printer"+".txt")

   # We need to convert the data into an array of [byte]
   [Byte[]]$devModeAry = $strdevmode.split(" ")

   #Write the data into the registry on the remote machine
   $printerRegKey.setvalue("Default Devmode",$devModeAry,"BINARY")
   Write-Host "Done restoring Registry"
  }
 ELSE
 {
   Write-Host ("c:\Mandatory\Print\devmode\$printer"+".txt") + "not found"
 }
}

$fileout = "c:\filnavn.txt"
$fileObj = New-Item -ItemType file $fileout -Force



#Export Printer Dev Mode Settings
$ErrorActionPreference = "silentlycontinue"
$RasterSequenceDEC = "82 65 83 84 69 82 77 79 68 69"
[string]$strByte = ""

$computers=Get-CTX5PrintServers SY $args | %{$_.properties.name}
#$computers = "B3562S99"
foreach($computer in $computers)
{
  Write-Host "Processing $computer"
 $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $computer)
 $regKey = $reg.OpenSubKey("Software\Microsoft\windows nt\CurrentVersion\Print\printers",$true)
 $printers = $regKey.GetSubKeyNames()
 [Boolean]$restartSpooler=$false

 foreach($printer in $printers)
 {
  $PrinterRegKey= $reg.OpenSubKey("Software\Microsoft\windows nt\CurrentVersion\Print\printers\$printer",$true)
  $devModeAry = $PrinterRegKey.GetValue("Default DevMode")
  foreach($byt in $devModeAry)
  {
   [string]$strByte = $strByte +" "+ $byt
  }
  $strByte = $strByte.substring(1)
  if($strByte -match $RasterSequenceDEC)
  {
    $restartSpooler=$true
   Write-Host -ForegroundColor Yellow "Found raster on printer $printer on $computer"
   $tekst="Found raster on printer $printer on $computer"
   Add-Content $fileObj $tekst
   SetDevModeToVector $printer $PrinterRegKey
 
  }
  ELSE
  {
   $strByte | Out-File c:\Mandatory\Print\DevMode\$printer.txt
  }

  $strByte=$null
  $PrinterRegKey.Close()
 }
 $regKey.close()
 $reg.close()
 if($restartSpooler -eq $true)
 {
  Restart-RemoteService -computer $computer -service Spooler
 }
}

This script contains a costumiced commandlet; Restart-RemoteService. This commandlets are a part of a module i wrote, which is loaded on every server in the forest. 

Restart-Remoteservice takes a service and a computer as input and will restart the given service on the given computer.  Easy and simple, not very elegant, but it gets the job done :)

Ingen kommentarer:

Send en kommentar