Gezien het feit dat er meer dan 100 printqueues op de oude printserver aanwezig waren en ik geen vertrouwen had in printbrm (nieuwe drivers, vervuiling) heb ik wat scripts gebruikt om de migratie uit te voeren.
Als eerste de poorten aangemaakt, de laatste WHQL Universal drivers van de diverse fabrikanten geinstalleerd en op driver isolation gecontrolleerd, de printers aangemaakt en de printqueues omgezet.
Inhoud
1. Poorten toevoegen:
2. Drivers installeren:
3. Driver isolation:
4. Printers aanmaken:
5. Oude printserver ontmantelen
6. Omzetten van de printer queue:
Oude printserver: PS01
Nieuwe printserver: PS02
1. Poorten toevoegen:
Stap1:
Met behulp van Powershell een lijst gemaakt van alle printerpoorten die op de PS01 gebruikt werden door printers die gedeeld waren en in een bestand opgeslagen met de naam "tcpipports.txt":
get-wmiobject win32_printer -ComputerName PS01 -Filter 'shared=true' | format-table PortName –auto | Out-File tcpipports.txt
Hieronder een snippet van tcpipports.txt:
< -------------------------------------------------- >
10.100.1.130
10.107.1.130
10.108.1.130
10.11.1.130
10.111.1.130
10.112.1.130
< -------------------------------------------------- >
Stap2:
Op de nieuwe printserver (PS02) een map aangemaakt c:\scripts en daar het prnport.vbs bestand in gekopieerd. Tevens prnmgr.vbs erin gekopieerd, deze heb je nodig om later printers aan te maken (stap 3 onder kopje 4. Printers aanmaken).
Met prnport.vbs kun je via de command prompt printer poorten aanmaken. Voor meer informatie voer het commando cscript prnport.vbs /h uit.
(prnport.vbs oorspronkelijke locatie: “C:\Windows\System32\Printing_Admin_Scripts\en-US”)
Stap3:
Batch bestand aangemaakt die een voor een de poorten aanmaakt met de juiste parameters:
for /f %%a in (c:\scripts\tcpipports.txt) do cscript c:\scripts\prnport.vbs -a -r %%a -h %%a -o raw -n 9100 -md
pause
2. Drivers installeren:
Downloaden / locatie drivers:
Persoonlijk probeer ik omgevingen zo uniform te houden. Wat in dit geval inhoud dat ik de laatste WHQL PCL Universal Printer drivers download en deze installeer.
De drivers zowel 32- als 64-bit dienen te worden gedownload en worden opgeslagen op de PS02 in de map:
C:\Printerdrivers\Fabrikantnaam\64-bit
C:\Printerdrivers\Fabrikantnaam\32-bit
Installatie:
Onder het kopje drivers in de Pinter Management Console kun je drivers (zowel 32- als 64-bit) toevoegen. Bij het installeren van de 32-bit driver krijg je de eerste keer echter een foutmelding:
Please provide path to Windows media (x86 processor)
Je moet nadat je de foutmelding hebt weggeklikt het path opgeven naar de ntprint.inf van een 32bits windows 7 systeem. In mijn geval:
\\ws01\c$\Windows\winsxs\x86_ntprint.inf_31bf3856ad364e35_6.1.7601.17514_none_3d0806ed18f4fa43
Daarna wordt de 32-bit driver gewoon geïnstalleerd.
De printerdrivers worden in de driverstore (“C:\Windows\System32\DriverStore\FileRepository”) geplaatst. Deze kun je beheren met pnputil.exe.
Je kunt bijvoorbeeld een overzicht van alle 3rd party packages verkrijgen met het commando:
C:\>pnputil -e
Microsoft PnP Utility
Published name : oem0.inf
Driver package provider : RICOH
Class : Printers
Driver date and version : 07/15/2011 3.7.0.0
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem10.inf
Driver package provider : RICOH
Class : Printers
Driver date and version : 07/15/2011 3.7.0.0
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem12.inf
Driver package provider : KONICA MINOLTA
Class : Printers
Driver date and version : 03/23/2011 1.20.11.0
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem21.inf
Driver package provider : Kyocera Mita Europe B.V.
Class : Printers
Driver date and version : 12/01/2010 2.10.1201
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem13.inf
Driver package provider : Kyocera Mita Europe B.V.
Class : Printers
Driver date and version : 12/01/2010 2.10.1201
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem14.inf
Driver package provider : KONICA MINOLTA
Class : Printers
Driver date and version : 03/23/2011 1.20.11.0
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem16.inf
Driver package provider : HP
Class : Printers
Driver date and version : 12/17/2010 61.111.01.9108
Signer name : Microsoft Windows Hardware Compatibility Publisher
Published name : oem17.inf
Driver package provider : HP
Class : Printers
Driver date and version : 12/17/2010 61.111.01.9108
Signer name : Microsoft Windows Hardware Compatibility Publisher
........
3. Driver isolation:
We hebben het allemaal wel eens meegemaakt. Een crash van de print spooler, vaak gevolgd door klagende gebruikers die niet meer kunnen printen. En naast een paperless office is er een andere oplossing in zicht.
Met de komst van Windows 2008R2 (en ook Windows 7) heeft Microsoft een aantal verbeteringen doorgevoerd in de print spooler. De belangrijkste is misschien wel het isoleren van de printerdrivers. In de NT4 tijd waren de printerdrivers nog uitgevoerd als kernel drivers. Een bug in de printerdriver kon er voor zorgen dat je hele server vast liep. Dit werd in Windows 2000 aangepast. User-mode printer drivers werden ingevoerd. Een slechte printerdriver zorgde nu alleen voor een crash van het printspooler subsysteem. Toch was dat, met name op multi-user omgevingen (centrale printservers, terminal server omgevingen) leverde het crashen van het print spooler subsysteem veel ergernissen op bij de gebruikers. Het is dan ook niet meer dan logisch dat Microsoft heeft gezocht naar een manier om printer drivers nog verder te isoleren. Iets wat ze dus met 2008R2 gelukt is.
Als we dan iets verder kijken dan zien we dat Driver isolation standaard aan staat op een Windows 2008R Server. Vervolgens kunnen we per printer driver aangeven in welke isolation mode deze moet functioneren:
- None – Print drivers worden geladen in het print spooler sub systeem; eigenlijk is dit vergelijkbaar met het model wat gebruikt werd in oudere windows versies.
- Shared – Drivers worden geladen in een apart proces wat gescheiden is van de printspooler. Printerdrivers kunnen elkaar onderling nog wel dwars zitten. Deze mode is de standaard.
- Isolated – Elke printer driver wordt gestart in een eigen proces. Niet alleen de print spooler wordt op deze manier beschermd maar ook andere drivers.
Dit klinkt natuurlijk heel mooi maar de adder onder het gras is dat printer drivers wel zodanig gemaakt moeten worden dat ze Driver isolation ondersteunen.
Om er achter te komen of een print driver gebruik kan maken van isolation kan je kijken in het meegeleverde .inf bestand. Als een driver geschikt is voor printer isolation dan is DriverIsolation=2 terug te vinden in het .inf bestand. Als dat er niet staat of deze waarde 0 is dan wordt print driver isolation helaas niet ondersteund en is het tijd om een verzoek hiervoor neer te leggen bij de printer fabrikant. Zoals je echter hieronder kunt zien, ondersteunen de meeste fabrikanten driverisolation.
4. Printers aanmaken:
Stap1:
De printers van de PS01 moeten nu aangemaakt worden op de PS02. Hiervoor is het handig om een overzicht te maken van de printers met bijbehorende printerpoorten van de PS01.
De manier om dat te verkrijgen is door gebruik te maken van een Powershell commando:
get-wmiobject win32_printer -ComputerName PS01 -Filter 'shared=true' | format-table Name,PortName,DriverName –auto | Out-File addpr.txt
Dit geeft onderstaand overzicht:
< -------------------------------------------------- >
Name PortName DriverName
---- -------- ----------
PR-VerkoopAdministratie IP_10.0.9.30 Kyocera Mita FS-3820N KX
PR-Spreekkamer IP_10.0.9.18 HP LaserJet 2300 Series PCL 6
PR-Openbaar1 IP_10.0.9.17 Kyocera KM-4050 KX
PR-Openbaar2 IP_10.0.9.17 Kyocera KM-4050 KX
PR-Openbaar3 IP_10.0.9.17 Kyocera KM-4050 KX
< -------------------------------------------------- >
Stap2:
Deze output vervolgens aangepast zodat alleen de Name,PortName en DriverName zichbaar waren en deze aan elkaar geplakt zaten gescheiden door een “,”.
De DriverName dmv search and replace aangepast zodat de printer aangemaakt wordt met de nieuwe driver. (Kyocera KM-4050 KX wordt Kyocera Classic Universaldriver (A4 models))
< -------------------------------------------------- >
P-Albertuslaan-2,10.52.1.130,Kyocera Classic Universaldriver (A4 models)
P-Amundsenstraat-58,10.35.1.130,Kyocera Classic Universaldriver (A4 models)
P-Appelterstraat-5,10.1.1.130,Kyocera Classic Universaldriver (A4 models)
P-Hertogenlaan-13,10.6.1.130,Kyocera Classic Universaldriver (A4 models)
< -------------------------------------------------- >
Eventueel handige extra te gebruiken powershell scripts:
Script1:
Je kunt de output ook naar een bestand wegschrijven door gebruik te maken van de Out-File optie:
get-wmiobject win32_printer -ComputerName PS01 -Filter 'shared=true' | format-table Name,ShareName,PortName,DriverName –auto | Out-File printers.txt
Eventueel kun je het ook in een CSV of HTML formaat wegschrijven. Je moet dan de output eerst converteren met pipe naar ConvertTo-CSV of ConvertTo-Html.
Script2:
Om een overzicht te krijgen van alle eigenschappen van een printer, kun je gebruik maken van onderstaand script:
get-wmiobject win32_printer | %{if ($_.default) {$_}} | fl *
Deze geeft alle eigenschappen van je standaard printer weer.
Status : Unknown
Name : KX DRIVER for Universal Printing
__GENUS : 2
__CLASS : Win32_Printer
__SUPERCLASS : CIM_Printer
__DYNASTY : CIM_ManagedSystemElement
__RELPATH : Win32_Printer.DeviceID="KX DRIVER for Universal Printing"
__PROPERTY_COUNT : 86
__DERIVATION : {CIM_Printer, CIM_LogicalDevice, CIM_LogicalElement, CIM_ManagedSystemElement}
__SERVER : LT002043
__NAMESPACE : root\cimv2
__PATH : \\LT002043\root\cimv2:Win32_Printer.DeviceID="KX DRIVER for Universal Printing"
Attributes : 580
Availability :
AvailableJobSheets :
AveragePagesPerMinute : 0
Capabilities : {4, 2, 3, 5}
CapabilityDescriptions : {Copies, Color, Duplex, Collate}
Caption : KX DRIVER for Universal Printing
CharSetsSupported :
Comment :
ConfigManagerErrorCode :
ConfigManagerUserConfig :
CreationClassName : Win32_Printer
CurrentCapabilities :
CurrentCharSet :
CurrentLanguage :
CurrentMimeType :
CurrentNaturalLanguage :
CurrentPaperType :
Default : True
DefaultCapabilities :
DefaultCopies :
DefaultLanguage :
DefaultMimeType :
DefaultNumberUp :
DefaultPaperType :
DefaultPriority : 0
Description :
DetectedErrorState : 0
DeviceID : KX DRIVER for Universal Printing
Direct : False
DoCompleteFirst : True
DriverName : KX DRIVER for Universal Printing
EnableBIDI : False
EnableDevQueryPrint : False
ErrorCleared :
ErrorDescription :
ErrorInformation :
ExtendedDetectedErrorState : 0
ExtendedPrinterStatus : 2
Hidden : False
HorizontalResolution : 600
InstallDate :
JobCountSinceLastReset : 0
KeepPrintedJobs : False
LanguagesSupported : {2, 2, 6, 2...}
LastErrorCode :
Local : True
Location :
MarkingTechnology :
MaxCopies :
MaxNumberUp :
MaxSizeSupported :
MimeTypesSupported :
NaturalLanguagesSupported :
Network : False
PaperSizesSupported : {7, 8, 1, 1...}
PaperTypesAvailable :
Parameters :
PNPDeviceID :
PortName : 10.0.3.16
PowerManagementCapabilities :
PowerManagementSupported :
PrinterPaperNames : {Letter, Legal, Ledger (11 x 17), 12 x 18...}
PrinterState : 0
PrinterStatus : 3
PrintJobDataType : RAW
PrintProcessor : winprint
Priority : 1
Published : False
Queued : False
RawOnly : False
SeparatorFile :
ServerName :
Shared : False
ShareName :
SpoolEnabled : True
StartTime :
StatusInfo :
SystemCreationClassName : Win32_ComputerSystem
SystemName : LT002043
TimeOfLastReset :
UntilTime :
VerticalResolution : 600
WorkOffline : False
Scope : System.Management.ManagementScope
Path : \\LT002043\root\cimv2:Win32_Printer.DeviceID="KX DRIVER for Universal Printing"
Options : System.Management.ObjectGetOptions
ClassPath : \\LT002043\root\cimv2:Win32_Printer
Properties : {Attributes, Availability, AvailableJobSheets, AveragePagesPerMinute...}
SystemProperties : {__GENUS, __CLASS, __SUPERCLASS, __DYNASTY...}
Qualifiers : {dynamic}
Site :
Container :
Script3:
Je kunt met powershell ook een specifiek overzicht verkrijgen door filters toe te passen:
get-wmiobject win32_printer -ComputerName PS02 -Filter 'DriverName="KONICA MINOLTA Universal PCL"' | format-table Name,ShareName,PortName,DriverName -auto
Stap3:
Batch aangemaakt die ervoor zorgt dat alle printers met de juiste driver en printerpoort worden aangemaakt. Batchbestand maakt gebruikt van de in Stap 1 gegenereerde lijst van printers.
for /f "tokens=1,2,3 delims=," %G in (c:\scripts\addpr.txt) do cscript c:\scripts\prnmngr.vbs -a -p "%G" -m "%I" -r "%H"
Stap4:
Omdat het vrij snel gedaan is heb ik ervoor gekozen om handmatig via de Printer Management Console alle printers te delen en in te stellen.
5. Oude printserver ontmantelen
Stap1:
Verwijderen van de printers uit de Active Directory.
Met onderstaand powershell commando eerst een overzicht gemaakt van alle PS01 printers waar de optie “list in directory” aangevinkt stond:
get-wmiobject win32_printer -ComputerName PS01 -Filter 'published=true' | Sort-Object Name | format-table Name,Location,Published -auto | Out-File PS01PrintersPublished.txt
Vervolgens met onderstaand script het item “Published” voor alle printers op PS01 op false gezet.
Dit script moet wel op de PS01 zelf uitgevoerd worden!
$printers = gwmi win32_printer
foreach ($printer in $printers)
{
$printer.published = $false
$printer.put()
}
Stap 2:
Nu de printers niet meer in de AD voorkomen, worden ze ook niet meer toegevoegd door de gebruikers. Wel kunnen ze nog steeds van de printqueues gebruik maken. De printers zijn immers nog gedeeld.
Nu is het van belang dat printerqueue wordt omgezet. Zie het volgende kopje.
Stap3:
Als na een paar weken alle queues zijn omgezet, je moet gebruikers die op vakantie zijn ook de gelegenheid geven om een keer in te loggen zodat de queue wordt omgezet, kun je de server uit zetten.
6. Omzetten van de printer queue:
Voor het omzetten van de door gebruikers toegevoegde gedeelde printers naar de nieuwe printserver dient onderstaand commando uitgevoerd te worden. Dit kan in een batchbestand geplaatst worden echter kan het ook in het loginscript verwerkt worden.
Cscript \\salfischbergerit.local\netlogon\qchange\qchange.vbs \\salfischbergerit.local\netlogon\qchange\changes.txt //NoLogo
(Het script maakt gebruik twee bestanden “qchange.vbs” en “changes.txt”.)
Hieronder een snippet uit het loginscript dat gebruik maakt van bovenstaand commando en plaatst daarnaast een controle sleutel in het register om te kijken of het commando al een keer is uitgevoerd.
'<-------------------------------------------------->
' BEGIN - PRINTERWIJZIGINGEN DOORVOEREN
'--------------------------------------------------------------------------------
' UITLEG:
' Dit script zorgt ervoor dat de gebruikers die gebruik maken van een printqueue op de ps01 automatisch overgezet worden naar de printqueue van de ps02.
On error resume next
'***********************************************************************
sKey = WshShell.RegRead ("HKCU\Korein\Printerwijziging") 'Lees Registry Key uit
If sKey <> "Doorgevoerd" Then
iRetourwaarde = WSHShell.Run("cscript \\salfischbergerit.local\netlogon\qchange\qchange.vbs \\salfischbergerit.local\netlogon\qchange\changes.txt //NoLogo",7,TRUE)
WshShell.RegWrite "HKCU\YITA\Printerwijziging retourwaarde", iRetourwaarde, "REG_SZ"
WshShell.RegWrite "HKCU\YITA\Printerwijziging", "Doorgevoerd", "REG_SZ"
End If
'***********************************************************************
On error goto 0
'--------------------------------------------------------------------------------
' EINDE - PRINTERWIJZIGINGEN DOORVOEREN
'<-------------------------------------------------->
Qchange.vbs
' This VBS script can be used to update a user's printer connections (Print Mappings)
' In addition to switching to a different Print Queue (or Print Server ) the script will also also preserve the user's current default printer. i.e if their default printer is renamed then the new name will be set as their default.
' Multiple queues can be moved at once. The changes required are listed in a simple text file, the script will ignore any other print connections not explicitly listed.
' Execute the script like this: cscript qchange.vbs changes.txt //NoLogo
' Opmerking: gebruik "net view \\server" om een overzicht te krijgen van de printers op een server. Let er wel op, dat er gebruik wordt gemaakt van de "display" name van de printer ipv sharename.
On Error Resume Next
Const VERBOSE = "Y" 'Display progress (Y or N)
Const Title = "Print Connection Migrator"
Const ForReading = 1
Dim strDefaultPrinter
Dim InstalledPrinters 'Array of printer names
Dim Textfile 'File with print Q names
Dim OldPrintQueues() 'Dynamic array to store old print queue names, from the text file
Dim NewPrintQueues() 'Dynamic array to store new print queue names, from the text file
Dim fso 'File System Object
Dim objTextFile 'Text file object
Dim strNextLine 'Line of the text file
Dim i
Dim WshNetwork
Set WshNetwork = CreateObject("WScript.Network")
' 1. - Get the command line args ###
SET Parameters = Wscript.arguments
'If no command line arguments provided, quit
If Parameters.Count = 0 Then
WScript.Quit(1)
Else
Textfile = Parameters.item(0)
End If
If Textfile = "" or Not Right(TextFile,4) = ".txt" or Not FileExist(Textfile) Then
Error=MsgBox("No valid input file provided. Stopping the script now.",vbokonly, Title)
WScript.Quit(1)
End If
If VERBOSE = "Y" Then Wscript.Echo "Reading input file"
' 2. Read the text file and import it in a Array ###
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile (TextFile, ForReading)
i=-1
While not objTextFile.AtEndOfStream
i = i+1
Redim Preserve OldPrintQueues(i)
ReDim Preserve NewPrintQueues(i)
strLine = objTextFile.Readline
'Do not import the comment lines
If Left(strLine,2) = "\\" Then
OldPrintQueues(i) = Left(strLine,InStr(strline,";")-1)
If VERBOSE = "Y" Then Wscript.Echo " old Q is: " & OldPrintQueues(i)
NewPrintQueues(i) = Mid(strline,InStr(strline,";")+1,Len(strline))
If VERBOSE = "Y" Then Wscript.Echo " new Q is: " & NewPrintQueues(i)
End If
Wend
objTextFile.Close
' 3. Store the name of the default Printer ###
strDefaultPrinter = DefaultPrinter
If VERBOSE = "Y" Then Wscript.Echo " Default is: " & strDefaultPrinter
' 4. WMI query for current printer connections ###
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colInstalledPrinters = objWMIService.ExecQuery _
("Select * from Win32_Printer")
' 5. Main Loop through printer collection ###
For Each objPrinter in colInstalledPrinters
If VERBOSE = "Y" Then Wscript.Echo " Current connection: " & objPrinter.Name
If Left(objPrinter.Name, 2) = "\\" Then 'Work only On network printers
'Search the corresponding printer and create it
i = 0 'set the indice at the beginning of the array (prepare to loop)
Do Until i > UBound(OldPrintQueues)
If UCase(objPrinter.Name) = UCase(OldPrintQueues(i)) Then
'Create the connection to the new printer
If VERBOSE = "Y" Then Wscript.Echo " New connection: " & NewPrintQueues(i)
WshNetwork.AddWindowsPrinterConnection NewPrintQueues(i)
If UCase(strDefaultPrinter) = UCase(objPrinter.Name) Then 'This is the default printer
'Set the default Printer
WshNetwork.SetDefaultPrinter NewPrintQueues(i)
End If
'Delete the printer connection
WshNetwork.RemovePrinterConnection objPrinter.Name
If VERBOSE = "Y" Then Wscript.Echo " Removing : " & objPrinter.Name
End If
i = i + 1
Loop
End If 'End of check for network printers
Next 'End of the loop through the printers of this user
Set WshNetwork = Nothing
'-----------------
' Functions
'-----------------
'Return the default printer
Function DefaultPrinter
Dim strComputer
Dim Result
strComputer = "."
Result = ""
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colInstalledPrinters = objWMIService.ExecQuery _
("Select * from Win32_Printer")
For Each objPrinter in colInstalledPrinters
If objPrinter.Default = True Then
Result = objPrinter.Name
End If
Next
DefaultPrinter = Result
End Function
'-----------------
'Does File Exist (Boolean)
Function FileExist (FileFullPath)
Dim Fso
Set Fso = CreateObject("Scripting.FileSystemObject")
If (Fso.FileExists(FileFullPath)) Then
FileExist = True
Else
FileExist = False
End If
End Function
' Based on a script by: Sebastien Pittet (pittet.org)
' discussed at http://cwashington.netreach.net/
' Creative Commons Attribution-ShareAlike 2.5
' http://creativecommons.org/licenses/by-sa/2.5/
' Simon Sheppard Sept 2005
' http://www.ss64.com/nt/syntax-qchange.html
Changes.txt
Met onderstaand script een output gemaakt van alle gedeelde printers van de PS01.
get-wmiobject win32_printer -ComputerName PS01 -Filter 'shared=true' | Sort-Object Name | format-table Name -auto | Out-File ps01names.txt
Aangezien de printernaam hetzelfde is gebleven was het mogelijk om in Excel wat kolommen toe te voegen en vervolgens in notepad te plakken en deze modificeren totdat deze eruit ziet als onderstaand snipsel:
< -------------------------------------------------- >
\\PS01\P-Acaciaweg-24;\\PS02\P-Acaciaweg-24
\\PS01\P-Adriannastraat-4;\\PS02\P-Adriannastraat-4
\\PS01\P-Albertlaan-2;\\PS02\P-Albertlaan-2
\\PS01\P-Amundsenstraat-55;\\PS02\P-Amundsenstraat-55
< -------------------------------------------------- >
Geen opmerkingen:
Een reactie posten