Skip to content

Instantly share code, notes, and snippets.

@xxami
Last active March 29, 2024 13:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save xxami/39dd65645f98f6a67635 to your computer and use it in GitHub Desktop.
Save xxami/39dd65645f98f6a67635 to your computer and use it in GitHub Desktop.
C# example of printing pdf - Windows
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Printing;
using System.Diagnostics;
using System.Printing;
using System.IO;
using System.Threading;
Console.WriteLine("select printer n to test!\n");
/**
* lookup installed printers
*/
for (int i = 0; i < PrinterSettings.InstalledPrinters.Count; i++) {
Console.WriteLine(" " + i + " => " + PrinterSettings.InstalledPrinters[i]);
}
Console.WriteLine("");
string printer = "";
int n;
if (!int.TryParse(Console.ReadKey().KeyChar.ToString(), out n) || n >= PrinterSettings.InstalledPrinters.Count) {
Console.WriteLine("\n\ninvalid printer!\n");
return;
}
Console.WriteLine("\n");
printer = PrinterSettings.InstalledPrinters[n];
/**
* local print queue (data used in "see what's printing" ui in windows)
*/
PrintQueue print_queue = LocalPrintServer.GetDefaultPrintQueue();
string file_name = "test.pdf";
Console.WriteLine("printing to ........................ " + printer);
Console.WriteLine("listening for ...................... " + file_name);
/**
* print the pdf using one of two methods
*
* 1. using shellexecute/printto uses whatever program is setup in the registy
* to print that type of file (ie. when you right click print in explorer)
*
* 2. sumatrapdf offers commandline printing which, unlike adobe reader does
* not force a UI on the user
*/
#if USE_SHELL_EXECUTE
Process print = new Process();
print.StartInfo.FileName = file_name;
print.StartInfo.UseShellExecute = true;
print.StartInfo.Verb = "printto";
print.StartInfo.CreateNoWindow = true;
print.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
print.StartInfo.Arguments = printer;
print.Start();
#else
Process print = new Process();
print.StartInfo.FileName = "sumatrapdf.exe";
print.StartInfo.UseShellExecute = true;
print.StartInfo.CreateNoWindow = true;
print.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
print.StartInfo.Arguments = "-print-to \"" + printer + "\" -exit-when-done \"" + file_name + "\"";
print.Start();
#endif
PrintSystemJobInfo target_job;
/*
* scan for job (identified by filename)
*/
while (true) {
print_queue.Refresh();
PrintJobInfoCollection info = print_queue.GetPrintJobInfoCollection();
foreach (PrintSystemJobInfo job in info) {
if (job.Name.Substring(job.Name.LastIndexOf("\\") + 1) == file_name) {
target_job = job;
goto outer_loop;
}
}
Thread.Sleep(50);
}
outer_loop:
Console.WriteLine("\nfound target \"" + file_name + "\" job in queue!\n");
/**
* build initial list of properties about the job so far
*/
PrintJobStatus _status = target_job.JobStatus;
bool _offline = target_job.IsOffline;
bool _iserror = target_job.IsInError;
int _pages_printed = target_job.NumberOfPagesPrinted;
bool _printing = target_job.IsPrinting;
bool _printed = target_job.IsPrinted;
bool _completed = target_job.IsCompleted;
Console.WriteLine("job id ............................. " + target_job.JobIdentifier);
Console.WriteLine("job status ......................... " + _status);
Console.WriteLine("job number of pages ................ " + target_job.NumberOfPages);
Console.WriteLine("printer online? .................... " + ((_offline) ? "OFF" : "ON"));
Console.WriteLine("\nmonitoring for status changes!\n");
Thread.Sleep(50);
/*
* scan for updates by checking against those properties
* note: this won't always exit because it is not guarenteed
* that the iscompleted status will be set
*/
while (!_completed) {
target_job.Refresh();
if (target_job.JobStatus.ToString() != _status.ToString()) {
_status = target_job.JobStatus;
Console.WriteLine("job status changed to .............. " + _status);
}
if (target_job.IsOffline != _offline) {
_offline = target_job.IsOffline;
Console.WriteLine("printer status changed to .......... " + ((_offline) ? "OFF" : "ON"));
}
if (target_job.IsInError != _iserror) {
_iserror = target_job.IsInError;
Console.WriteLine("job error state changed to ......... " + ((_iserror) ? "ERROR" : "OK"));
}
if (target_job.NumberOfPagesPrinted != _pages_printed) {
_pages_printed = target_job.NumberOfPagesPrinted;
Console.WriteLine("job n pages printed changed to ..... " + _pages_printed + "/" + target_job.NumberOfPages);
}
if (target_job.IsPrinting != _printing) {
_printing = target_job.IsPrinting;
Console.WriteLine("job print state changed to ......... " + ((_printing) ? "PRINTING" : "NOT_PRINTING"));
}
if (target_job.IsPrinted != _printed) {
_printed = target_job.IsPrinted;
Console.WriteLine("job print state changed to ......... " + ((_printed) ? "PRINTED" : "NOT_PRINTED"));
}
if (target_job.IsCompleted != _completed) {
_completed = target_job.IsCompleted;
Console.WriteLine("job print state changed to ......... " + ((_completed) ? "COMPLETED" : "NOT_COMPLETED"));
}
Thread.Sleep(50);
}
Console.WriteLine("\n finished bye~bye! ");
Console.ReadKey();
@xxami
Copy link
Author

xxami commented Apr 3, 2015

completed/printed status are not usually set, deleted/deleting status seem to be the most reliable thing to check to see if a print job is finishing/has finished. i like to compare the number of printed pages to the total number of pages in the document to determine if the job printed successfully or not, though PrintSystemJobInfo.NumberOfPages has been a very unreliable property in my testing so i find that it is best to calculate from the file on disk.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment