Generating XPS Automagically

I got a mail overnight asking about ways to automatically generate XPS from applications, specifically asking for a way to enable existing applications that don't have knowledge of XPS to generate XPS content. The Microsoft XPS Document Writer (MXDW) allows you to do this, irrespective of whether you're using the .Net or Win32 platforms. There's two ways that applications can invoke MXDW. The first is via the normal action of a user printing, where MXDW is explicitly selected as the target printer. When using this route MXDW displays a 'Save As' dialog so the user can set the target XPS filename. The second route is where the application programmatically selects MXDW as the printer, in this case it can automatically set the output filename by setting lpszOutput in DOCINFO [1] [2]. Typically this route would be invoked by an user selecting 'Save As XPS' in the interface, with the application taking advantage of the print subsystem to do most of the work.

MSDN documentation snapshot If you don't want users to select the filename (perhaps you want the file saved to some magic folder for further processing), and you're not in a position to modify the application to support setting the destination with DOCINFO, then there is another option [3]. Microsoft makes available the core components of MXDW as part of the Windows Driver Kit (available on Microsoft Connect and MSDN Subscriber Downloads). Using the WDK it is possible to build a custom XPS print driver (XPSDrv) that automates the output process, including doing much more than just setting a destination filename automatically. The WDK even includes samples that illustrate modifying the XPS content using the Filter Pipeline Interfaces within XPSDrv. Using this approach a third party could, relatively easily, provide a 'Print to Custom Workflow' print driver which generates XPS. A second advantage of this approach is that the custom driver can also specify configuration options that are aligned with the requirements of the downstream workflow, rather than relying on the generic settings exposed by the standard MXDW printer.

An obvious question is "Why doesn't MXDW provide a way to set a destination automatically without requiring code in the application?" Technically, this would be rather straightforward (or at least, as straightforward as anything is when you have as many customers and partners as Windows), but the bigger problem is the consistency of user experience. For the larger scenario — enabling XPS to be submitted to some downstream workflow — you really want the destination to be explicit, for example by providing the ability to print to a destination that identifies the workflow. Here's what I mean:

image

Implementing by building a custom driver on the XPSDrv foundation is a nice clean way of enabling this scenario.

 

Footnote:

[1] The app can also do this when a user has explicitly selected MXDW as the printer, although this isn't recommended since the user experience might not be quite what the user expected.

[2] Feng has the details.

[3] Actually, there's more than one other option, for example see this post from Feng, although note the limitations!