C# PrintQueue получить работу надежно при печати с Adobe Reader
Я столкнулся с проблемой, когда мне нужно вызвать Adobe Reader для печати PDF в фоновом режиме. Я пробовал несколько других программ и библиотек, но пока только Adobe Reader дал желаемые результаты при печати файлов PDF.
Проблема в том, что, поскольку это фоновая задача, я должен запустить Adobe Reader, а затем снова закрыть его после завершения. К сожалению, я не нашел способа определить, закончила ли Reader печать. Поэтому я попытался проверить PrintQueue
Я печатаю для завершения работы. Пока это то, что я придумал:
internal class AdobeReaderPrint
{
const string regSoftware = @"SOFTWARE\Microsoft\Windows\CurrentVersion";
private string printServerName;
private string printerName;
private string acroRead;
private volatile string pdfFile = null;
private volatile bool jobComplete = false;
internal AdobeReaderPrint(string printerName)
{
acroRead = Registry.LocalMachine.OpenSubKey(regSoftware + @"\App Paths\AcroRd32.exe").GetValue("").ToString();
if (!File.Exists(acroRead))
throw new FileNotFoundException("Adobe Reader wurde nicht auf dem System gefunden.");
var printer = printerName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
this.printServerName = printer.Length > 1 ? printer[0] : null;
this.printerName = printer[printer.Length - 1];
var printServer = new PrintServer($@"\\{printServerName}");
var printQueue = new PrintQueue(printServer, printerName);
}
public void PrintAndWait(string pdfFile)
{
jobComplete = false;
if (!File.Exists(pdfFile))
throw new FileNotFoundException("Die Datei konnte nicht gefunden werden", pdfFile);
this.pdfFile = pdfFile;
var arguments = $"/n /s /o /h /t {pdfFile} \"\\\\{printServerName}\\{printerName}\"";
var startInfo = new ProcessStartInfo(acroRead, arguments)
{
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
Task.Run(() => { CheckPrintQueue(); });
var reader = Process.Start(startInfo);
while (!jobComplete)
Thread.Sleep(100);
reader.Kill();
}
private void CheckPrintQueue()
{
var printServer = new PrintServer($@"\\{printServerName}");
var printQueue = new PrintQueue(printServer, printerName);
PrintSystemJobInfo job = null;
while (!jobComplete)
{
if (job == null)
{
foreach (var item in printQueue.GetPrintJobInfoCollection())
{
if (pdfFile.Contains(item.Name))
{
job = item;
}
}
}
else
{
job.Refresh();
if (job.JobStatus == PrintJobStatus.Deleted)
jobComplete = true;
}
Thread.Sleep(1);
}
}
}
Это работает, пока я могу поймать задание некоторое время с задачей, выполняющей CheckPrintQueue()
-метод. Однако иногда работа проскальзывает и никогда не будет записана. Теперь, хотя добавление тайм-аута к методу проверки по крайней мере приведет к завершению программы, я все равно хотел бы знать, что задание действительно напечатано - это событие, которое я пропустил.
Так как PrintQueue
а также PrintJob
У объектов нет событий, на которые можно подписаться, и они работают только с помощью опроса. Я действительно не знаю, что мне следует делать, чтобы не пропустить всю работу.
Я бы предпочел не использовать pinvoke и подписываться на хуки очереди печати Windows для контроля выполнения задания. Есть ли другой способ сделать это?