Posts Tagged ‘Printing’

Printer Migration Client Script

November 3rd, 2009

If you have ever had to migrate all the printers from one Windows print server to another, the server side part is pretty easy.  Windows 2008 includes the Printer Migration Wizard which can migrate the queues.  Prior to Windows 2008 there was an outstanding utility called Print Migrator (PrintMig) which made it a snap.

However the client side is a bit more tricky.  Since there is a different server name in the printer share path the clients will be broken after the migration.

Printer share  path on old server: \\OldPrnSrv\Printer1

Printer share path on new server: \\NewPrnSrv\Printer1

This problem can be further complicated if during the migration you took the opportunity to standardize Printer/Printer Share names.  I had this exact problem at a client.  I solved it with a GPO-based logon script and input file.  Before I go into how to implement this, first a little about the script.

  • The script first checks for the existence of a “check” file.  If the check file exists then we assume the script already ran and we exit.
  • Then the script records the user’s default printer as it will need this info later to ensure the same device is set as default after the printer reconnect.
  • Next the script walks through the input file and attempts to disconnect each “old” printer connection and reconnect to the new.  If the printer share in the input file is not defined on the person’s machine then it skips that line and moves on to the next line/printer.
  • Once all the input file has been traversed the script resets the person’s default printer and creates the “check” file.

Here is the script code.

On Error Resume Next
Const ForReading = 1

Set WshNetwork = CreateObject("WScript.Network")
Set fso = CreateObject("Scripting.FileSystemObject")
If Not fso.FileExists("c:\PrinterReconnectFinished.txt") then
Set f1 = fso.OpenTextFile(GetPath() & "input.txt", ForReading)

varDefault = GetDefaultPrinter()

tmpArr = Split(f1.readall, vbcrlf)
for i = 0 to UBOUND(tmpArr)
    If instr(1, tmpArr(i), varDefault, 1) then x = i
    err.clear
    tmpVar = split(tmpArr(i), "~")
    WshNetwork.RemovePrinterConnection tmpVar(0)
    If err.number = 0 then WshNetwork.AddWindowsPrinterConnection tmpVar(1)
next

var1 = split(tmpArr(x), "~")
ConfigDefaultPrinter(var1(1))
    Set f2 = fso.CreateTextFile("c:\PrinterReconnectFinished.txt", True)
    Set f3 = fso.Getfile("c:\PrinterReconnectFinished.txt")
    f3.attributes = f3.attributes + 2
End If

'*************************************************************************************************
Sub ConfigDefaultPrinter(name)
        '*****************************************************************************************
        '*****************************************************************************************
        ' Purpose:  This sub routine defines a default printer based on the printer name passed to
        ' it.
        ' Version 1.0
        ' Arguements:  None
        '*****************************************************************************************
        '*****************************************************************************************
    strComputer = "."
    Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & _
    strComputer & "\root\cimv2")
    Set colInstalledPrinters =  objWMIService.ExecQuery _
    ("Select * from Win32_Printer Where Name = 'name'")
    For Each objPrinter in colInstalledPrinters
            objPrinter.SetDefaultPrinter()
    Next
End Sub
'*************************************************************************************************

'*************************************************************************************************
Function GetDefaultPrinter()
        '*****************************************************************************************
        '*****************************************************************************************
        ' Purpose:  This Function returns the default printer as configured on the client.
        ' Version 1.0
        ' Arguements:  None
        ' Returns:  Text string
        '*****************************************************************************************
        '*****************************************************************************************
    strComputer = "."
    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 then
            GetDefaultPrinter = objPrinter.Name
        End If
    Next
End Function
'*************************************************************************************************

'*************************************************************************************************
Function GetPath()
    '*********************************************************************************************
    '*********************************************************************************************
    ' Purpose:  This Function returns the path where the script is currently being executed.
    ' Version 1.0
    ' Arguements:  None
    ' Returns:  Text string
    '*********************************************************************************************
    '*********************************************************************************************
    Dim path
    path = WScript.ScriptFullName
    GetPath = Left(path, InStrRev(path, "\"))
End Function
'*************************************************************************************************

Here’s how you can implement this solution.

1. Create an input file and put each old printer share path and new share path on a new line separated by a “~”.  It should look like this:

\\OldPrnSrv1\Printer1~\\NewPrnSrv1\Printer1
\\OldPrnSrv1\Printer2~\\NewPrnSrv1\Printer1
etc...

2. When you have all the printer share paths entered in your input file save it as input.txt.

3. Next download the printer migration script here.  Strip the “.txt” off of the end of the name.

4. Save the input.txt and script files in the domain scripts share (\\mydomain.com\SYSVOL\mydomain.com\scripts).

5. Create a new Group Policy Object (GPO) called Printer Reconnect. NOTEDon’t link it to any container yet.

6. Edit the GPO under User Configuration>Windows Settings>Scripts double-click Logon.

7. Click the Add button, then Browse.  Locate/select the PrinterReconnect.vbs script in the path you saved it to previously.

8. Click OK and make sure the script is displayed on the Logon Properties screen.  Click OK.

Once all printers are migrated to the new server and well tested, you should be ready to have the clients reconnect to the migrated queues on the new server.  ONLY when ready to have clients reconnect, go to the next step.

9. Link the Printer Reconnect GPO to an appropriate container to apply the logon script to targeted users.

As always, use this at your own risk.  Let me know if you have any issues and I will help out as I can.