Rethinking Network Printing (with new PConn2 IPM Utility)
If you’re like me and insist on controlling the printer drivers that are installed and used on your TS/RDS/XenApp servers (you should!), Windows network printing has historically been a nightmare: print servers only let you connect a printer if you have the exact same driver as the one with which the printer is defined (unlike RDP and ICA client printing which offer driver name substitution mechanisms), attempt to download and install said driver to your server otherwise (sometimes even when you in fact do have an identically named driver, and inexplicably sometimes even if you have the identical driver version), and can reject connections entirely if you attempt to use “Point and Print” or “Packaged Point and Print” Restrictions Policies to prevent driver installations. This state of affairs is often exacerbated by the fact that your servers’ Windows version does not match that of the (generally older) print server(s), which often means that “in-box” driver names for the same printer models don’t match across platforms (there ought to be a law!) and is further complicated when you have no control over the cowboys who manage the print servers and who sadistically ignore the (much safer) in-box drivers, always installing drivers from vendor downloads.
And yet, preferable though client printing may be (driver substitution feature, universal driver availability, better compression, automatic reconfiguration based on detected client printers, etc.), providing some network printing capability is often a customer requirement. For example, if there are thin client devices in use in the environment, creating client-side printer connections can range from absurdly difficult to outright impossible – users of such devices may have no choice but to rely on network printer connections established within their remote sessions (what Citrix calls “session printers” when connected via the XenApp feature by that name). Another common example is that of home or traveling users who need to print to an office printer, either for later pickup or for immediate use by a colleague or assistant. (“Are assistants colleagues?” Discuss. :))
So, with these preliminaries in mind, here are a few items related to resolving the above issues, ranging from mundane to mind-blowing :):
A. Unexpected re-installations of existing printer drivers when establishing network printer connections from a Windows 2008 R2 SP1 RDS/XA server can be at least partially eliminated by installing hotfix “KB2896881 – Long logon time when you use the AddPrinterConnection VBScript command to map printers for users during logon process in Windows Server 2008 R2 SP1”. Despite the article’s title, the hotfix reduces driver re-installations regardless of the method used to create printer connections, including KiXtart, XenApp “Session Printers” and “manual” network printer additions. This is a worthwhile hotfix to apply even if you wind up using some of the “fancier” strategies described below.
B. As of Windows Vista and continuing through all current workstation and server versions of Windows, a new network printing method called “Client-Side Rendering” has become the default, unless disabled via the “Always render print jobs on the server” policy setting. With client-side rendering, the printer’s native command sequence required to get the job onto paper (i.e. the actual PCL or PostScript or whatever commands) is generated entirely on the client side of the printing connection (i.e. within the session in an RDS/XA scenario) via the locally installed printer driver, and is then sent as a RAW stream to the print server which in turn dumps it off to the printer without any further processing by its own printer driver. Wait a minute! The print server takes whatever printer commands we send it and passes them on to the printer, no questions asked?? Then why the @#$%&! does it constantly bust our b@##$ about the matching printer driver requirement?? Or is that really a requirement after all? The following intriguing sentence is found at the bottom of the above-mentioned policy’s description:
Note: In cases where the client print driver does not match the server print driver (mismatched connection), the client will always process the print job, regardless of the setting of this policy.
Huh?! Mismatched connection?? Sounds great! How do I get me one of those? The answers (there are two) turn out to be buried in a single sparsely detailed MSDN article, and neither one is available via any built-in (or, as far as I can tell, third-party) GUI or command line Windows tool or printer connection method, … until today that is! :) This seems to be a case of the Windows API having outpaced the user-accessible capabilities of Windows, so the feature lays there, dormant.
Before I describe the two available methods for creating “mismatched” printer connections, let me address something that you may run across regarding Client-Side Rendering and the above “server-side rendering” policy, for example in this Microsoft blog: “There is one scenario where it may be desirable to offload the rendering policy to the print server – and that would be on a Terminal Server”. The idea here is that print job rendering can be somewhat processor-intensive, so the suggestion is that it might be best kept on the print server if you fear massive amounts of printing occurring simultaneously on multi-user machines. That may be true, especially on underpowered machines (<insert VM joke here>), and you can certainly use the policy if you find it beneficial (as you saw above, it won’t affect mismatched printer connections anyway), but I have news for you: you’ve been rendering print jobs on Terminal Servers since long before Windows 2008! How? With ICA/RDP client printing! All client printing (except to printers created with the Citrix Universal Printer Driver) is rendered within the session using a local (possibly substituted) driver and the raw PCL/PostScript/etc. stream is sent to the client for immediate pass-through to the printer – sound familiar?
Okay, back to printer connections with mismatched drivers. Here are the two ways you can create them:
- If, for any given shared printer, you create on the print server a REG_SZ value named “DriverPolicy” under the key HKLMSYSTEMCurrentControlSetControlPrintPrinterNamePrinterDriverData and set it to the name of the driver you would like to use when connecting to this printer (regardless of the driver with which it’s actually defined), then any Windows Vista or above client (including Windows 2008 R2) will only use that particular driver when connecting to that printer, assuming it’s available locally. There is even a benefit to creating this Registry entry (set to the printer’s “real” driver name) when you in fact do have the matching driver on the client side and are okay with using it: it dramatically speeds up the establishment of connections to that printer because it completely short circuits all driver name and version comparisons, and eliminates even the possibility of a driver being downloaded from the print server. But that is both the strength and the (slight) weakness of this technique: while Windows XP/2003 print clients are oblivious to and unaffected by the DriverPolicy Registry entry (since they don’t support client-side rendering in the first place), it “breaks” Point-and-Print for the more current Windows versions – if they don’t already have the requested driver locally, no attempt will be made to provide them with one and connection attempts to that printer will simply fail. That’s of course not a problem for you and your carefully managed RDS/XA servers (which will already have the requested drivers and will benefit from the elimination of all the “driver drama”), but print servers usually also support workstations, and their set of installed printer drivers is rarely managed with any sort of care (because Point-and-Print makes that unnecessary). Workarounds that come to mind include either using separate print servers for RDS/XA sessions (if we could easily have that, we probably wouldn’t be having this discussion) or creating duplicate printer shares with recognizably different names, one without a DriverPolicy entry (for use on workstations) and one with (for use on RDS/XA).
There is a Windows API function called AddPrinterConnection2 that, when correctly used (I had an embarrassingly hard time figuring it out :)), will let you create a printer connection using the specified locally installed driver of your choice. As in the case of the DriverPolicy Registry entry described above, there is a significant performance benefit to using this function even if you specify the same driver as the print server’s, again because it bypasses all driver version comparisons and never involves a driver download. But unless you’re building this capability into a custom program, you need a utility that “wraps” the API function in question and makes it available to batch files and other scripts, … which is where the new PConn2 utility comes in. See the screenshot below for its syntax and usage notes.
Two empirical observations about this API function (and therefore about PConn2): (a) It creates “mismatched” connections exactly as requested within the current logon session (don’t go by the printer connection’s Properties when confirming the driver it’s using – it’s in the Registry somewhere – ask me if you want to know exactly where), but if the user account has a persistent profile (i.e. local or roaming, not mandatory) and logs off then logs back on, Windows will dutifully reestablish the printer connection without employing the correct API function and the requested driver mismatch, so you may still wind up with unexpected driver downloads. Not a problem with mandatory profiles, but in other scenarios you’ll need to either delete HKCUPrintersConnections at logoff or exclude it from capture by whatever profile “solution” you’re using. (b) The function bypasses all policy restrictions on print servers to which you may print – this is actually a great feature: if you use this function (or PConn2) to create all user printer connections under tight script control, then you can exclude all print servers via policy (by only allowing printing to a single nonexistent “bogus” server) and rest assured than no other mechanism can be used to create printer connections that might result in unwanted driver downloads.
C. If you’re forward-looking, you’ll be interested in a new feature introduced with the Windows 8/2012 “v4” printer driver architecture, the so-called “Class Drivers”: printer vendors (and Microsoft) can now provide these “super-drivers” that support from a single model to an entire range of printers from any given manufacturer (e.g. “Xerox PCL6 Class Driver” or “Brother PS Class Driver”) and print clients, including Windows 7 and 2008 R2, can connect and print to any shared printer defined with such a class driver using a single client-side printer driver, the “Microsoft Enhanced Point and Print Compatibility Driver”. Could be a game changer! At the very least something to consider if you have the option of building (or suggesting) a Windows 2012-based printing environment.
Well, if you aren’t by now as sick of reading about printing as I am of writing about it, you’re in need of serious help.