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).
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:
prt by Jane
*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.