Files
docs-desktop/dotnet-desktop-guide/framework/wpf/advanced/how-to-programmatically-print-xps-files.md
T
Andy (Steve) De George be103da07e Replace various WPF include files with content (#1335)
* net-current-v30plus-md.md

* net-current-v40plus-md.md

* tla2sharptla-ui-md.md

* tla2sharptla-uiautomation-md.md

* tla2sharptla-winclient-md.md

* tla2sharptla-xaml-md.md

* tlasharptla-ui-md.md

* tlasharptla-uiautomation-md.md

* tlasharptla-winclient-md.md

* tlasharptla-xaml-md.md

* fix warnings
2022-03-16 12:14:11 -04:00

7.0 KiB

title, ms.date, dev_langs, helpviewer_keywords, ms.assetid
title ms.date dev_langs helpviewer_keywords ms.assetid
How to: Programmatically Print XPS Files 03/30/2017
csharp
vb
printing XPS files programmatically [WPF]
XPS files [WPF], printing programmatically
0b1c0a3f-b19e-43d6-bcc9-eb3ec4e555ad

How to: Programmatically Print XPS Files

You can use one overload of the xref:System.Printing.PrintQueue.AddJob%2A method to print XML Paper Specification (XPS) files without opening a xref:System.Windows.Controls.PrintDialog or, in principle, any user interface (UI) at all.

You can also print XPS files using the many xref:System.Windows.Xps.XpsDocumentWriter.Write%2A?displayProperty=nameWithType and xref:System.Windows.Xps.XpsDocumentWriter.WriteAsync%2A?displayProperty=nameWithType methods. For more information, see Printing an XPS Document.

Another way of printing XPS is to use the xref:System.Windows.Controls.PrintDialog.PrintDocument%2A?displayProperty=nameWithType or xref:System.Windows.Controls.PrintDialog.PrintVisual%2A?displayProperty=nameWithType methods. See Invoke a Print Dialog.

Example

The main steps to using the three-parameter xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 method are as follows. The example below gives details.

  1. Determine if the printer is an XPSDrv printer. See Printing Overview for more about XPSDrv.

  2. If the printer is not an XPSDrv printer, set the thread's apartment to single thread.

  3. Instantiate a print server and print queue object.

  4. Call the method, specifying a job name, the file to be printed, and a xref:System.Boolean flag indicating whether or not the printer is an XPSDrv printer.

The example below shows how to batch print all XPS files in a directory. Although the application prompts the user to specify the directory, the three-parameter xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 method does not require a user interface (UI). It can be used in any code path where you have an XPS file name and path that you can pass to it.

The three-parameter xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 overload of xref:System.Printing.PrintQueue.AddJob%2A must run in a single thread apartment whenever the xref:System.Boolean parameter is false, which it must be when a non-XPSDrv printer is being used. However, the default apartment state for .NET is multiple thread. This default must be reversed since the example assumes a non-XPSDrv printer.

There are two ways to change the default. One way is to simply add the xref:System.STAThreadAttribute (that is, "[System.STAThreadAttribute()]") just above the first line of the application's Main method (usually "static void Main(string[] args)"). However, many applications require that the Main method have a multi-threaded apartment state, so there is a second method: put the call to xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 in a separate thread whose apartment state is set to xref:System.Threading.ApartmentState.STA with xref:System.Threading.Thread.SetApartmentState%2A. The example below uses this second technique.

Accordingly, the example begins by instantiating a xref:System.Threading.Thread object and passing it a PrintXPS method as the xref:System.Threading.ThreadStart parameter. (The PrintXPS method is defined later in the example.) Next the thread is set to a single thread apartment. The only remaining code of the Main method starts the new thread.

The meat of the example is in the staticBatchXPSPrinter.PrintXPS method. After creating a print server and queue, the method prompts the user for a directory containing XPS files. After validating the existence of the directory and the presence of *.xps files in it, the method adds each such file to the print queue. The example assumes that the printer is non-XPSDrv, so we are passing false to the last parameter of xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 method. For this reason, the method will validate the XPS markup in the file before it attempts to convert it to the printer's page description language. If the validation fails, an exception is thrown. The example code will catch the exception, notify the user about it, and then go on to process the next XPS file.

[!code-csharpBatchPrintXPSFiles#BatchPrintXPSFiles] [!code-vbBatchPrintXPSFiles#BatchPrintXPSFiles]

If you are using an XPSDrv printer, then you can set the final parameter to true. In that case, since XPS is the printer's page description language, the method will send the file to the printer without validating it or converting it to another page description language. If you are uncertain at design time whether the application will be using an XPSDrv printer, you can modify the application to have it read the xref:System.Printing.PrintQueue.IsXpsDevice%2A property and branch according to what it finds.

Since there will initially be few XPSDrv printers available immediately after the release of Windows Vista and Microsoft .NET Framework, you may need to disguise a non-XPSDrv printer as an XPSDrv printer. To do so, add Pipelineconfig.xml to the list of files in the following registry key of the computer running your application:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows NT x86\Drivers\Version-3\<PseudoXPSPrinter>\DependentFiles

where <PseudoXPSPrinter> is any print queue. The machine must then be rebooted.

This disguise will enable you to pass true as the final parameter of xref:System.Printing.PrintQueue.AddJob%28System.String%2CSystem.String%2CSystem.Boolean%29 without causing an exception, but since <PseudoXPSPrinter> is not really an XPSDrv printer, only garbage will print.

Note

For simplicity, the example above uses the presence of an *.xps extension as its test that a file is XPS. However, XPS files do not have to have this extension. The isXPS.exe (isXPS Conformance Tool) is one way of testing a file for XPS validity.

See also