Last active
March 29, 2024 13:38
-
-
Save xxami/39dd65645f98f6a67635 to your computer and use it in GitHub Desktop.
C# example of printing pdf - Windows
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.