Update 5/16/2017: Thanks to tabularasa for some improvements to this, fixing some missing slashes among other things!
In years past, logon scripts were the bane of many logon experiences due to their synchronous nature. Beginning with Windows 7, logon scripts can be processed asynchronously. We glossed over this fact: “Nice feature, but how will it help us? We’re heavily invested into GP Preferences now!” However, now that we’re 1078 virtual desktops deep, logon time is a serious concern. Citrix has failed to provide us with a way to extend the time on the automatic “log off if log on takes more than 90 seconds” feature. In most cases, this isn’t an issue, but this limitation highlighted a serious flaw: Even under normal circumstances, there are some cases where some users might exceed 90s.

Our organization uses the HP Universal Print driver, Ricoh Universal Print driver and the Lexmark Universal print driver and we map printers with Group Policy Preferences. This mapping process takes, on an “average” printer, 6-7 seconds. Unfortunately, this processing does in fact run synchronously (possibly due to GPP Drive mapping – I just found this article but it requires further testing! Would be interesting if this whole mess could be avoided by moving drive mapping out of GPO!) and therefore can add substantial time to the logon process. Some users have 5-15 printers available to them, bringing the practical limit to the number of printers to something like 10 (given that portions of the logon process require some time).

As we are heavily invested in preferences, item level targeting and (as everyone is) short on staff / training, we decided to leverage that investment in GPP but still gain the benefits of the logon script. A colleague of mine, Matt Heckman, created a rather ingenious Powershell script that effectively uses GPP Printer entries from a “dummy” GPO to map printers for our VDI environment. This means that our level 1 admins can still create printers using GPP with simple filters and the users in VDI will automatically map them. The results were substantial: A logon that took 60 seconds to reach a desktop was shortened by 45 seconds! In K-12, logon time is king as it directly translates into instructional time.

So, how does it work?

Create a new GPO. It is not required to link it anywhere in the domain. Be sure to clearly name it so that someone doesn’t think that it is an unused GPO!

Copy your existing printer preferences into the new GPO.

Modify the logon script to reflect the name/GUID of your new GPO. To obtain the GUID, in GPMC click the “details” tab, then copy the “Unique ID”. If you use any filters other than computer name or security group name you will need to extend the script.

write-host"`r`n The driver for $($sharedPrinter.Properties.path) doesn't appear to be present. The driver that needs to be installed is $($driverName.drivername). Please install this driver on the XenApp Server. `n`r"

Are you able to manually map the printers that are passing the mapping by simply browsing to the print server and opening the printer? Are there any events in the event viewer (Check application and also Applications & services, Microsoft, PrintService, Admin)?

The theory behind this is awesome. Just wanted to mention a few things the original poster did not mention…

In this line, you need to replace both contoso.local with your domain name
[xml]$printersXml = Get-Content “\contoso.localsysvolcontoso.localPolicies$GPOGuidUserPreferencesPrintersPrinters.xml”

In this line, it assumes you are using the Create action, not update or replace. Change to U or R if you use either of those.
if ($sharedPrinter.Properties.action -eq ‘C’) {

Even after modifying these two sections, this script was still not working for me. It would say the printer name, but there would be nothing after filters passed:. Filtering was not working for us at all. Since we only care about the groups that the computer is in, and our computers will only be in 1 printer group, I removed all the filtering and added a line for each one of our printer groups. Fill domainname, groupname, and GPOGuid to your organization.
if ($computerGroups -eq “DOMAINNAMEGROUPNAME”) {$GPOGuid = “{GUIDofPrinterPolicyForThisGroup}”}

The printer add, default, and delete lines were not working for us either. I modified the add to the following:
if ($sharedPrinter.Properties.action -eq “U”) {
Write-Host Installing Printer: “$($sharedPrinter.name)”
Write-Host UNC Path: “$PrinterPath”
(New-Object -ComObject WScript.Network).AddWindowsPrinterConnection($PrinterPath)
}
We use ‘Update’ not ‘Create’. I also had to make similar changes to the default and delete sections. Now this script is working like a champ. Thanks!

We originally found update prefs in general applied in 200ms where create was approximately 4ms, so with large numbers of preferences, it was a big savings. Since this script bypasses all that it is really up to you. I’ll check into the default printer business, there may have been an update to the script after this post but it was working. The result printer business was annoying with upm because the printer wasn’t necessarily mapped at the time of the application of upm, so it would reset to default.

Thanks for info. Every environment is different, so very well could have been working for you. I’ve seen no other posts on the internet in regards to deploying printers this way. Group Policy Printer Preferences are easy to manage but the slow log-ins were also a big problem for us. This let us use GPP but still have fast log-ins. So thanks for sharing!

Forgot $printerpath variable needs to be declared since that is not in original script. I’m no powershell expert but this worked for us for add, set default, and delete sections. Hope this helps anyone who can’t get the original script to work.

Drive mappings are an interesting beast, because they _always_ run synchronously in the login process in prefs. Moving them to the login script should provide a mild improvement, but drive mappings should be pretty fast by default as you’re not dealing with printer mojo. I’ve only seen them behave slowly when using DFS namespaces with invalid folders (non existent or no permissions for example) with the default timeout (120 min). Printers will run asynchronously when Group policy isn’t in first-run mode. You’d need to modify the script to iterate over the drive mapping section, rather than printers. You could map them using something like “New-PSDrive -name X -psprovider FileSystem -root c:scripts
“

The reason I’m asking about drive mappings is not to reduce logon time, more to resolve an issue.

The issue I have is that we use VPN. When logging in from a cafe for example, the user logs into their machine using a cached AD logon, then connects to the cafe wifi via a landing page. Once wifi is established they connect to the corporate network using VPN. The problem with GPPref drive mappings is that it is a foreground process, meaning it can only apply during startup or logon which in this case has already taken place.
We do have the option of calling a logon script from the VPN, but I don’t want to have to maintain both GPPrefs and an additional login script. What I would like to do, like your printer script, would be to create a GPO that contains my drive mappings (GPP) and then use a powershell script to process it. That way admins would maintain the GPO and the script would do the work.

Hi, Sorry it’s been a long time before replying – I meant to do it sooner and well..you know how it goes in the busy world of I.T. Thanks for dropping by my website and taking the time to comment on my post about our similar issue. Yeah..GPP printer deployment isn’t the bees-knees we all hoped it would be! Ah well – at least we both found a solution!