using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Printing; using System.Threading; using System.Threading.Tasks; using System.Windows; namespace CodeSampleCsharp { /// /// Interaction logic for MainWindow.xaml. /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private async void BtnPrint_Click(object sender, RoutedEventArgs e) { // Check that the folder exists. if (!Directory.Exists(txtFolderPath.Text)) { MessageBox.Show("First select a valid folder path."); return; } // Check whether any XPS files exist in the folder. string[] xpsFilePaths = Directory.GetFiles(path: txtFolderPath.Text, searchPattern: "*.xps"); if (xpsFilePaths.Length == 0) { MessageBox.Show("No XPS files found."); return; } // Determine whether XPS validation is needed. bool fastCopy = cbxValidateXps.IsChecked == false; // Batch add a collection of XPS files to the print queue. // Run asynchronously to avoid blocking the UI thread. bool isAllPrinted = await BatchAddToPrintQueueAsync(xpsFilePaths, fastCopy); // Show result message. MessageBox.Show($"{(isAllPrinted ? "Added" : "Failed to add")} all documents to the print queue."); } // /// /// Asyncronously, add a batch of XPS documents to the print queue using a PrintQueue.AddJob method. /// Handle the thread apartment state required by the PrintQueue.AddJob method. /// /// A collection of XPS documents. /// Whether to validate the XPS documents. /// Whether all documents were added to the print queue. public static async Task BatchAddToPrintQueueAsync(IEnumerable xpsFilePaths, bool fastCopy = false) { bool allAdded = true; // Queue some work to run on the ThreadPool. // Wait for completion without blocking the calling thread. await Task.Run(() => { if (fastCopy) allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy); else { // Create a thread to call the PrintQueue.AddJob method. Thread newThread = new(() => { allAdded = BatchAddToPrintQueue(xpsFilePaths, fastCopy); }); // Set the thread to single-threaded apartment state. newThread.SetApartmentState(ApartmentState.STA); // Start the thread. newThread.Start(); // Wait for thread completion. Blocks the calling thread, // which is a ThreadPool thread. newThread.Join(); } }); return allAdded; } /// /// Add a batch of XPS documents to the print queue using a PrintQueue.AddJob method. /// /// A collection of XPS documents. /// Whether to validate the XPS documents. /// Whether all documents were added to the print queue. public static bool BatchAddToPrintQueue(IEnumerable xpsFilePaths, bool fastCopy) { bool allAdded = true; // To print without getting the "Save Output File As" dialog, ensure // that your default printer is not the Microsoft XPS Document Writer, // Microsoft Print to PDF, or other print-to-file option. // Get a reference to the default print queue. PrintQueue defaultPrintQueue = LocalPrintServer.GetDefaultPrintQueue(); // Iterate through the document collection. foreach (string xpsFilePath in xpsFilePaths) { // Get document name. string xpsFileName = Path.GetFileName(xpsFilePath); try { // The AddJob method adds a new print job for an XPS // document into the print queue, and assigns a job name. // Use fastCopy to skip XPS validation and progress notifications. // If fastCopy is false, the thread that calls PrintQueue.AddJob // must have a single-threaded apartment state. PrintSystemJobInfo xpsPrintJob = defaultPrintQueue.AddJob(jobName: xpsFileName, documentPath: xpsFilePath, fastCopy); // If the queue is not paused and the printer is working, then jobs will automatically begin printing. Debug.WriteLine($"Added {xpsFileName} to the print queue."); } catch (PrintJobException e) { allAdded = false; Debug.WriteLine($"Failed to add {xpsFileName} to the print queue: {e.Message}\r\n{e.InnerException}"); } } return allAdded; } // } }