We have an application (ARIA MO) that has some special requirements. The application requires all printers used by it in the different locations to be manually loaded on the Citrix server with all drivers. This totals around 220 or some odd printers installed with around 15 different drivers loaded. The printers must have a local port and cannot be mapped via TCPIP or network mapping.
Our design goals for our Citrix environment are to minimize the various PVS images we use so we use various ‘layers’ to allow a single master image to be able to host various unique and difficult configurations. For this application we use AppV as our layering technology to put the application on the server, but for the printers we use a script to load them onto the server. What we have is a print server that hosts all the printers needed by this application and we can export the printers into a file using Print Management. Then we save that file on a network share somewhere. When the Citrix server boots, I can take that file and manipulate its contents to change the queues to ‘local’ queues then import that modified file to the Citrix server. I configured the script to take two parameters, a print file name and a server name. I call the script with a command line like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: :: :: Title: Install_Print_Queues.cmd :: :: By: Trentent Tye :: :: Date: 2014-09-05 :: :: Description: This script will take an input (a print server) and enumerate all of its print queues and then :: add them as global printers. Administrator permissions are required for the user context this script is run :: under as this script will also silently install print drivers. :: :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Starting Adding Printers" >NUL EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Starting importing printers from PrinterServer02" >NUL powershell.exe -executionPolicy byPass -file "C:\PublishedApplications\AHS-PrintExportFile-Import.ps1" -serverName PrinterServer02 -printFile "\\fileserver\ctx_apps\ARIAMO\PrinterServer02.printerExport" EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Completed importing printers from PrinterServer02" >NUL EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Starting importing printers from printServer01" >NUL powershell.exe -executionPolicy byPass -file "C:\PublishedApplications\AHS-PrintExportFile-Import.ps1" -serverName printServer01 -printFile "\\fileserver\ctx_apps\ARIAMO\PrintServer01.printerExport" EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Completed importing printers from printServer01" >NUL EVENTCREATE /ID 1 /L APPLICATION /T INFORMATION /SO "Local GP Startup Script - \"%~nx0"\" /D "Completed Adding Printers" >NUL |
The powershell command it calls is here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
################################################################################################ # # # Created by: Trentent Tye # Intel Server Team # IBM Canada Ltd. # # Creation Date: Oct 24, 2014 # Modified Date: # # File Name: AHS-PrintExportFile-Import.ps1 # # Description: This script will take a parameter "-serverName" that is pointed at a # print server and "-printFile" pointed at a '.printExport file. What it will # do is create Local Ports from a .printerExport file that comes from the Print # Server. From this it will create the local ports with the proper UNC path # and port name. # ################################################################################################ Param( [string]$serverName, [string]$printFile ) #check if eventlog exists, if not create it $commandName = $MyInvocation.MyCommand write-host $commandName if ([System.Diagnostics.EventLog]::SourceExists("Local GP Startup Script - ""$commandName'""") -eq $False) { New-EventLog -LogName "Application" -Source ("Local GP Startup Script - ""$commandName'""") } sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Starting PrinterExport-Import script") sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Import-Module ServerManager") ipmo ServerManager add-WindowsFeature Print-Server Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Getting NetView of {0}" -f $ServerName) $netView = net view $serverName | findstr /i /C:"Print " $netView = $netView -replace "\sPrint\s","," $netView = $netView -replace "\s","" $netView = $netView | ConvertFrom-CSV -Header "Printer" Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Number of printers detected: {0}" -f $netView.Printer.Count) #Remove Printer Exports from server if they already exist cd\ if (Test-Path -Path C:\printerExport) { Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Removing C:\printerExport") Remove-Item C:\printerExport -Force -Recurse } if (Test-Path -Path C:\modified.printerExport) { Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Removing C:\modified.printerExport") Remove-Item C:\modified.printerExport } foreach ($printer in $netView) { $printer = $printer.printer reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports" /v \\$serverName\$printer /T REG_SZ /f reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Ports" /v \\$serverName\$printer /T REG_SZ /f } #need to restart the spooler to enable the ports Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Restarting print spooler services to enable ports") net stop cpsvc /y sleep 2 net stop spooler /y sleep 2 net start spooler sleep 2 net start cpsvc sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Completed print spooler services to enable ports") #unpack printer properties file mkdir C:\printerExport C:\Windows\System32\spool\tools\PrintBRM.exe -R -D C:\printerExport -F $printFile Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Unpacked printerExport file") #modify printer properties echo `<PRINTERPORTS`>`</PRINTERPORTS`> > "C:\printerExport\BrmPorts.xml" #configure print queues cd C:\printerExport\Printers Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Configuring Print Queues") $files = ls foreach ($file in $files) { $xml = [xml](Get-Content $file) #blank sharename $xml.PRINTQUEUE.ShareName = "" #set attributes to 2624 which disables sharing $xml.PRINTQUEUE.Attributes = "2624" #configure portName to include \\server\printer $portName ="\\$serverName\" $portName += $xml.PRINTQUEUE.PortName | out-String $portName = $portName -replace "`n|`r" $xml.PRINTQUEUE.PortName = $portName $xml.PRINTQUEUE $path = "C:\printerExport\Printers\$file" $xml.Save($path) } # repack printerExport Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Repacking printerExport") C:\Windows\System32\spool\tools\PrintBRM.exe -B -D C:\printerExport -F C:\modified.printerExport # windows firewall needs to be enabled to import Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Starting Windows Firewall to import printers") sc.exe config MpsSvc start= auto sleep 2 net start MpsSvc sleep 2 # import changed file Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Importing print queues") C:\Windows\System32\spool\tools\PrintBRM.exe -R -F C:\modified.printerExport Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Completed importing print queues") sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Stopping and disabling Windows Firewall") net stop MpsSvc /y sc.exe config MpsSvc start= disabled #need to restart the spooler to alphabeticalize the printer list sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Restarting print services to alphabeticalize printer list") net stop cpsvc /y sleep 2 net stop spooler /y sleep 2 net start spooler sleep 2 net start cpsvc Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Finished restarting print services to alphabeticalize printer list") sleep 2 Write-EventLog –LogName APPLICATION –Source "Local GP Startup Script - ""$commandName'""" –EntryType Information –EventID 1 –Message ("Completed PrinterExport-Import script") |
So, what does this have to do with KB3170455? Well, since installing KB3170455 it prevents importing printer files with print drivers embedded. This is what it looks like with KB3170455 installed:
Without:
And the failure import with 3170455 installed:
Remove KB3170455 and the import works without issue.
Why Does Microsoft Have to Make This Process So Difficult?——-Why?!