====== Shared Network Printers ====== See also **[[networking:windows:printer_shared_gpp|Shared Network Printers Using GPP]]** FIXME This page is now just a collection of notes. For shared printers, we use GPP. :!: This subject has changed a lot with the advent of version 4 (V4) printer drivers in Windows 8 and 2012. **V4 Printing Overview**: http://www.computerperformance.co.uk/win8/windows8-v4-printer-driver.htm **Windows 8 Printing**: http://blogs.msdn.com/b/b8/archive/2012/07/25/simplifying-printing-in-windows-8.aspx ===== Group Policy Preferences ===== This is our current method for sharing networked Windows printers. See link above. ===== Group Policy ===== :!: We have **not** found publishing printers via GPO to be trouble free. * Can't set default printer ===== Windows Server 2008 with Multiple Drivers ===== - Add printer to server and confirm printing. - Download additional drivers and extract if necessary. Note the location. - Right click and select Printer Properties, Sharing tab, Share this printer. - Edit Share name (name displayed to users) if desired - Click Additional Drivers button. Select operating systems that would be using the printer. - Click OK, browse to driver location and install printer. When installing drivers for multiple architectures on a Windows Server, verify that the additional drivers are: * Same exact version * Same exact name ===== Per-Machine (Global) Network Printer Connections ===== **HowTo**: http://members.shaw.ca/bsanders/NetPrinterAllUsers.htm **User Guide**: http://download.microsoft.com/download/8/2/c/82cffcfa-56f6-4fc3-bfa5-80cd84793871/PrintUIUsersGuide.doc **Reference**: https://technet.microsoft.com/en-us/library/ee624057.aspx :!: Most network printer connections are only visible (usable) by the user that made the connection. Per-machine connections must be made by an administrator, but are **available to all users** of the machine. :!: You **must use the CLI** to manipulate global printers. Show per-machine (global) printer connections: Rundll32.exe printui.dll,PrintUIEntry /ge Delete per-machine (global) printer connection: Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp6700-lab" Add per-machine (global) printer connection: Rundll32.exe printui.dll,PrintUIEntry /ga /q /n"\\jw-dc1\hp6700-lab" Add per-machine (global) printer connection to a remote (workstation) computer: Rundll32.exe printui.dll,PrintUIEntry /ga /q /c"\\remotepcname" /n"\\jw-dc1\hp6700-lab" ===== Printer Tools ===== ==== adprintx.exe ==== http://windowsitpro.com/content/content/77369/adprintx.zip This is a simple commandline tool to add, delete and manipulate printers and is useful in scripts. ==== Set Default Printer.exe ==== http://www.dabcc.com/downloadfile.aspx?id=214 This is a small tool that pops up a window so a user can select their desitred default printer from a list. ==== PsExec.exe ==== https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx This tool is needed to clear out some protected registry keys. ===== Troubleshooting ===== **Important**: http://digitalzombies.com/2014/07/03/print_issues_rds_2012/ **Important**: http://community.spiceworks.com/topic/post/3939859 **Reset Printing (Lite and Full)**: http://blogs.technet.com/b/askperf/archive/2012/02/24/microsoft-fixit-for-printing.aspx * Deletes local printer devices too? Like PDFCreator? **Print Spooler Diagnostic**: https://support.microsoft.com/en-us/kb/2768706/en-us :!: Use **Winprint print processor** for all shared printers. :!: For RDS servers, **disable CSR** (client side rendering) for all shared printers. ==== Clear Out Print Queues ==== net stop spooler del /q /f "%systemroot%\system32\spool\printers\*.*" net start spooler ==== Delete Redirected Printers ==== Sometimes you'll get various redirected printers that you can't just delete... - Stop the print spooler - Use ''regedit'' to delete the problematic printer(s) from these keys: * ''HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers'' * ''HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Providers\LanMan Print Services\Servers\PrintServerName\PrinterName'' * ''HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\V4 Connections'' - Reboot the machine ==== Phantom Printers That Won't Go Away ==== :!: Make a **backup of your registry** before doing **anything**! You will need to launch ''regedit'' as the ''System'' user with ''PsExec'' to be able to clean out these keys. F:\Support\PsTools\PsExec -i -d -s c:\windows\regedit.exe Delete all numbered subkeys: HKLM\SYSTEM\CurrentControlSet\Control\Class\{1ed2bbf9-11f0-4084-b21f-ad83a8e6dcdc} Delete all ''##?#SWD#PRINTENUM#'' keys: HKLM\SYSTEM\CurrentControlSet\Control\DeviceClasses\{0ecef634-6ef0-472a-8085-5ad023ecbccd} Delete all subkeys containing ''SWD\PRINTENUM'' values under ''GUID\BaseContainers\GUID'': HKLM\SYSTEM\CurrentControlSet\Control\DeviceContainers\ Delete all subkeys: HKLM\SYSTEM\CurrentControlSet\Enum\SWD\PRINTENUM\ Then **reboot** the machine and check for 'phantom' printers in ''Add/Remove Printers''. Also check in Device Manager after enabling ''Show hidden devices''. ==== Problems Setting Default Printer ==== Possible cause: * The printer name under the ''HKEY_CURRENT_USER\Printers\Connections'' registry key does not match the case of the printer name under ''HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows:Device'' registry key. ===== Scripts ===== ==== PrintersReset.bat ==== :!: You might use this script if you use per-user (not global) printers. @echo off Echo Resetting printers... REM Delete all network printers F:\Support\Printer\adprintx.exe /f REM Wait a few seconds timeout /t 5 /nobreak > NUL REM Delete all network printers again to be sure F:\Support\Printer\adprintx.exe /f REM We don't install printers as regular users when using global printers so REM comment these lines out if using global printers Rundll32.exe printui.dll,PrintUIEntry /in /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /in /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /in /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /in /q /n"\\jw-dc1\mx350" REM Set a default printer, then let user choose a different one if desired Rundll32.exe printui.dll,PrintUIEntry /y /n"\\jw-dc1\hp8600-ofc" REM Let the user choose their default printer rem start "Select Your Default Printer" "F:\Support\Printer\Set Default Printer.exe" Echo. Echo The default printer has been reset to 'hp8600-ofc'. Echo. Echo Please reset your default printer if you want a different one. rem pause ==== PrintersClear.bat ==== :!: This is the script we usually use to let users reset their own printer configuration. It forces the user to log off. Printers are reinstalled via Group Policy Preferences when they log back in. @echo off echo Clearing network printers... Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\zm400-label" timeout /t 5 /nobreak Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\zm400-label" echo deleting some registry entries... echo. reg delete "HKEY_CURRENT_USER\Printers\DevModePerUser" /va /f reg delete "HKEY_CURRENT_USER\Printers\DevModes2" /va /f reg delete "HKEY_CURRENT_USER\Printers\Connections" /va /f reg delete "HKEY_CURRENT_USER\Printers\Defaults" /va /f reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Devices" /va /f reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" /va /f echo. echo. echo You must now log off (sign out - not disconnect) and log back in. echo. echo You will need to reset your default printer after logging back in. echo. echo Hit any key to log out or press ctrl-c to cancel. pause start c:\windows\system32\logoff.exe ==== PrintersClear - Global - Run as Admin.bat ==== @echo off echo This script must be run as administrator and will clear all network printers. echo. echo This script must be edited for each site. echo Deleting network printers... Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\zm400-label" echo Deleting global network printers... Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\zm400-label" timeout /t 5 /nobreak echo Doing it again in case the printers reappear... Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /dn /q /n"\\jw-dc1\zm400-label" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-lab" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\mx350" Rundll32.exe printui.dll,PrintUIEntry /gd /q /n"\\jw-dc1\zm400-label" echo Clearing out the registry... reg delete "HKEY_CURRENT_USER\Printers\DevModePerUser" /va /f reg delete "HKEY_CURRENT_USER\Printers\DevModes2" /va /f reg delete "HKEY_CURRENT_USER\Printers\Connections" /va /f reg delete "HKEY_CURRENT_USER\Printers\Defaults" /va /f reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\PrinterPorts" /va /f reg delete "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Devices" /va /f reg delete "HKEY_USERS\.DEFAULT\Printers\DevModePerUser" /va /f reg delete "HKEY_USERS\.DEFAULT\Printers\DevModes2" /va /f reg delete "HKEY_USERS\S-1-5-18\Printers\DevModePerUser" /va /f reg delete "HKEY_USERS\S-1-5-18\Printers\DevModes2" /va /f reg delete "HKEY_USERS\S-1-5-19\Printers\DevModePerUser" /va /f reg delete "HKEY_USERS\S-1-5-20\Printers\DevModePerUser" /va /f reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Connections" /va /f reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Providers\Client Side Rendering Print Provider" /f reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\V4 Connections" /f reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Print\Connections" /va /f reg delete "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Print\Providers\Client Side Rendering Print Provider" /f reg delete "HKEY_CURRENT_CONFIG\System\CurrentControlSet\Control\Print\Printers" /f reg delete "HKEY_CLASSES_ROOT\Local Settings\Printers\V4ConnectionCacheState" /va /f reg delete "HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default\AddIns\RDPDR" /f echo Clearing out any old print jobs... net stop spooler del /q /f "%systemroot%\system32\spool\printers\*.*" del /q /f "%systemroot%\system32\spool\servers\*.*" net start spooler echo Hit any key to open Device Manager. echo. echo Then click "View -> Show hidden devices" and delete any leftover printers there. pause start /wait devmgmt.msc echo You should now reboot to automatically recreate some of the deleted registry keys. pause ==== PrintersAdd - Global - Run as Admin.bat ==== :!: Global printers are available to all users of a machine when they log in. :!: Global printers can only be added or deleted by an admin. :!: There is no GUI way to add or remove global printers. REM Add global network printers for all users Rundll32.exe printui.dll,PrintUIEntry /ga /q /n"\\jw-dc1\hp8600-ofc" Rundll32.exe printui.dll,PrintUIEntry /ga /q /n"\\jw-dc1\hp6700-lab" Rundll32.exe printui.dll,PrintUIEntry /ga /q /n"\\jw-dc1\hp8600-mav" Rundll32.exe printui.dll,PrintUIEntry /ga /q /n"\\jw-dc1\mx350" REM Show global printers Rundll32.exe printui.dll,PrintUIEntry /ge ==== PrintersAddRemote - Global - Run as Admin.bat ==== @Echo off Echo. REM This batch file could be used to add global network printers to a workstation PC from the domain controller REM Check that a computer name was given as an argument if [%1]==[/?] goto usage Echo Adding global printers to the specified computer (%1)... rundll32 printui.dll,PrintUIEntry /ga /q /c\\%1 /n"\\jw-dc1\hp8600-ofc" rundll32 printui.dll,PrintUIEntry /ga /q /c\\%1 /n"\\jw-dc1\hp6700-lab" rundll32 printui.dll,PrintUIEntry /ga /q /c\\%1 /n"\\jw-dc1\hp8600-mav" rundll32 printui.dll,PrintUIEntry /ga /q /c\\%1 /n"\\jw-dc1\mx350" Echo Stopping the print spooler on the specified computer (%1)... start /wait sc \\%1 stop spooler Echo Starting the print spooler on the specified computer (%1)... start /wait sc \\%1 start spooler Echo Done! goto end :usage Echo No computer name was given. Echo. Echo Specify the computer that you want the global printers to be added to. :end pause ==== PrinterSetup.vbs ==== 'PrinterSetup.vbs ' 'Delete all network printers 'This will not delete local printers even if they are using TCP/IP ports On error resume next Set WshNetwork = WScript.CreateObject("WScript.Network") Set oPrinters = WshNetwork.EnumPrinterConnections For i = 0 to oPrinters.Count - 1 Step 2 WshNetwork.RemovePrinterConnection oPrinters.Item(i+1) Next 'Sleep period is in milliseconds WScript.Sleep(3000) 'Loop through and delete the network printers again For i = 0 to oPrinters.Count - 1 Step 2 WshNetwork.RemovePrinterConnection oPrinters.Item(i+1) Next ==== RemoveAllPrinters.vbs ==== Const NETWORK = 22 Set objNetwork = CreateObject("WScript.Network") strComputer = "." Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colPrinters = objWMIService.ExecQuery("Select * From Win32_Printer") For Each objPrinter in colPrinters If objPrinter.Attributes And NETWORK Then strPrinter = objPrinter.Name objNetwork.RemovePrinterConnection strPrinter End If Next ==== UpdatePrintQueues.vbs ==== ' ======================================================================= ' ' NAME: UpdatePrintQueues-v1b.vbs ' ' AUTHOR: Paul S. Chapman ' DATE : 7-5-2006 ' ' COMMENT: This script was built to allow administrators to migrate print ' queues from one server to another with no disruption to the end user. ' Uses RegistryItemExists function FAQ'd by djhawthorne on tek-tips: ' FAQ329-5864: Checking if Registry Key's or Value's exist '========================================================================== Option Explicit Dim strFlagsOn, arrDefault, strDefaultPrinter Dim objShell, objNetwork, objDict ' This may have changed in newer Windows versions? Const strDPKey = "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device" ' Check if command line argument "1" is passed to script. Enable verbose ' mode if argument is present. If WScript.Arguments.Count = 0 Then strFlagsOn = False Elseif WScript.Arguments.Item(0) = "1" Then strFlagsOn = True End If Set objNetwork = CreateObject("WScript.Network") Set objShell = CreateObject("WScript.Shell") Set objDict = CreateObject("Scripting.Dictionary") ' Log script start time objShell.LogEvent 4,"Update Printers Script Starting" ' Check if Default printer registry key exists. If not then quit ' because this is the first time the user has logged in. If RegItmExist(strDPKey) = False Then If strFlagsOn = True Then WScript.Echo "New User Profile. Quitting..." End If WScript.Quit End If ' Read Registry key that contains default printer into an array arrDefault = Split(objShell.RegRead(strDPKey), ",") ' Verify that an array was returned, then check if default printer is network printer If IsArray(arrDefault) Then If Left(arrDefault(0), 2) = "\\" Then strDefaultPrinter = arrDefault(0) If strFlagsOn = True Then WScript.Echo "Default Printer: " & strDefaultPrinter End If End If End If ' Populate Dictionary object with old and new printer names. Old printer ' is the key, and new printer is the item (or definition). ' Syntax: ' .Add "\\\", "\\\" ' ********** BEGIN EDIT AREA ********** With objDict .CompareMode = vbtextcompare .Add "\\OldServer\OldQueue1", "\\NewServer\NewQueue1" .Add "\\OldServer\OldQueue2", "\\NewServer\NewQueue2" End With [green]' ********** END EDIT AREA ********** ' Call sub to fix printers that are currently installed FixInstalled ' Reset Default printer, if it was replaced by "FixInstalled" sub. If objDict.Exists(strDefaultPrinter) Then objNetwork.SetDefaultPrinter objDict.Item(strDefaultPrinter) End If ' Log script end time objShell.LogEvent 4,"Update Printers Script Finished" Sub FixInstalled ' This sub enumerates the currently installed printers, then checks ' each one in turn against the Dictionary object to see if it has been ' replaced. If printer exists in dictionary, delete it and install the ' replacement printer. Dim ctr, objPrinters, strPrinter Set objPrinters = objNetwork.EnumPrinterConnections ' Check if printer is installed before attempting to delete. For Ctr = 0 To objPrinters.Count - 1 Step 2 If objDict.Exists(objPrinters.Item(ctr + 1)) Then strPrinter = objPrinters.Item(ctr + 1) If strFlagsOn = True Then WScript.Echo " Removing dead printer:" & strPrinter End If objNetwork.RemovePrinterConnection strPrinter If strFlagsOn = True Then WScript.Echo " Installing: " & objDict.Item(strPrinter) End If objNetwork.AddWindowsPrinterConnection objDict.Item(strPrinter) End If Next End Sub Function RegItmExist (RegistryItem) ' This function checks to see if registry key/value passed to it exists, ' and returns true if it does. If strFlagsOn = True Then WScript.Echo " Checking registry for: " & RegistryItem End If Dim ErrDescription On Error Resume Next 'Find out if we are looking for a key or a value If (Right(RegistryItem, 1) = "\") Then 'It's a registry key we are looking for. Try reading the key. objShell.RegRead RegistryItem Select Case Err Case 0: RegItmExist = True Case &h80070002: ErrDescription = Replace(Err.description, RegistryItem, "") Err.clear objShell.RegRead "HKEY_ERROR\" If (ErrDescription <> Replace(Err.description, "HKEY_ERROR\", "")) Then RegItmExist = True Else RegItmExist = False End If Case Else: RegItmExist = False End Select Else 'It's a registry value we are looking for. Try reading the value objShell.RegRead RegistryItem 'Catch the Error Select Case Err Case 0: RegItmExist = True Case Else RegItmExist = False End Select End If 'Turn error reporting back On On Error Goto 0 If strFlagsOn = True Then WScript.Echo " Item exists: " & RegItmExist End If End Function