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 для контроля выполнения задания. Есть ли другой способ сделать это?

0 ответов

Другие вопросы по тегам