Scenario:
You aquire a new network, and the naming schemes (yes, plural) are… not consistant. Also, the servers are running on Windows 2000/2003 still. So, you upgrade the servers to 2012 R2 and get their naming standardized. But what about those printers? To make matters worse, several departments cross-share printer usage in case of outages, and some managers have a printer or two dedicated just to themselves… as do some of the regular staff. You have been authorized to consolidate some of these, and just remove others. But with 500+ users on this network, you need to script it (or hire a small army of college students, but let’s leave that for another discussion).
Solution:
Now, your first task is to identify all the printers, and their ports. Then you assign new names to these printers matching your naming scheme. I like to put it all in an Excel spreadsheet, so I can see it and line things up easier. Once this is done, actually create and test each of the printers on the new server.
Once this is done, you need to point the users to these new queues. Start by exporting the columns for old and new printer names to two text files (I used “oldprinters.txt” and “newprinters.txt”), as shown below:
printer A
prn-2nd-from-left
prt by Jane
Mikes-printer
Bob
Timmy-queue
prn-maint-bw
prn-acct-bw
REMOVE
prn-sales-bw
prn-sales-clr
prn-mgmt-clr
prn-dev-bw
prn-maint-bw
*Make sure that the columns line up, so that each line in the new column matches up with the column you want to change from in the old column!
Now, every script out there that I can find won’t handle changing print queue names, or removing/consolidating certain printers. We need to just delete the old printers from the users, and we don’t want to add multiple copies of the same printer. So I came up with this solution.
' --Initialize script variables--
strComputer = "."
DefaultPrinter = 4
ReadOnlyFile = 1
NumPosition = 0
AddThisPrinter = "Yes"
'Change these four variables to match your environment
strOldServer = "\\Print-Srv\"
strNewServer = "\\SiteA-FPS-W12\"
strOldPrinters = "oldprinters.txt"
strNewPrinters = "newprinters.txt"
' --Initialize script objects--
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Wait until the user is really logged in...
strUserName = ""
While strUserName = ""
WScript.Sleep 100 ' 1/10 th of a second
Set objNetwork = WScript.CreateObject("WScript.Network")
strUserName = objNetwork.UserName
Wend
' --Generate a list of printers that this user has installed--
Set colInstalledPrinters = objWMIService.ExecQuery _
("Select * From Win32_Printer Where Network = True")
' --Generate a list of printer names from the old server--
Set objOldPrintersFile = objFSO.OpenTextFile(strOldPrinters, ReadOnlyFile)
strContents = objOldPrintersFile.ReadAll
colOldPrinterList = Split(strContents,vbNewLine)
' --Generate a list of printer names from the new server--
Set objNewPrintersFile = objFSO.OpenTextFile(strNewPrinters, ReadOnlyFile)
strContents = objNewPrintersFile.ReadAll
colNewPrinterList = Split(strContents,vbNewLine)
' --Iterate through the list of printers that this user has installed--
For Each objPrinter in colInstalledPrinters
' --Since For Each doesn't track index, keep track of it yourself--
NumPosition = 0
' --Iterate through all printer names located on old server--
For Each strOldPrinter in colOldPrinterList
' --We fould a match, so update it--
strOldPrinterID = strOldServer & strOldPrinter
If (objPrinter.DeviceID = strOldPrinterID) Then
Set objNetwork = CreateObject("WScript.Network")
' --Use that index we made to assign the new printer to a variable--
strNewPrinterUNC = strNewServer & colNewPrinterList(NumPosition)
' --Test to see if the new printer has already been set up (since we are many-to-one)--
' --Also skip to delete if new printer is marked REMOVE--
If (colNewPrinterList(NumPosition) <> "REMOVE") Then
Set colComparePrinters = objWMIService.ExecQuery _
("Select * From Win32_Printer Where Network = True")
AddThisPrinter = "Yes"
For Each objExistingPrinter in colComparePrinters
If (objExistingPrinter.DeviceID = strNewPrinterUNC) Then
AddThisPrinter = "No"
Exit For
End If
Next
' --Since printer doesn't exist, let's add it now--
If (AddThisPrinter = "Yes") Then
Set objNetwork = CreateObject("WScript.Network")
objNetwork.AddWindowsPrinterConnection strNewPrinterUNC
End If
' --We want to assign the equivalent printer as default after updating it--
If objPrinter.Attributes And DefaultPrinter Then
objNetwork.SetDefaultPrinter strNewPrinterUNC
End If
End If
' --Now delete the old printer, since that server is going away--
objNetwork.RemovePrinterConnection objPrinter.DeviceID, true, true
End If
' --And increment our index into the new printer names table
NumPosition = NumPosition + 1
Next
Next
“Awesome! That worked perfectly, Jim!… Wait… It worked when I tested it as Administrator. But when I put it in the logon script, the screen goes black for like 10 minutes and it doesn’t work!”.
You’ve just run into a little “feature” of the User Account Control (UAC) feature of Windows 7+. Users need elevated privileges to add a printer driver. Now, I obviously don’t think we should make all the users admins just to be able to run a script! So, I found a write-up by someone over on MSDN who explains how to work around this, in detail.