Ошибка при одновременной печати на принтере Microsoft Print на PDF из нескольких потоков / приложений - PullRequest
2 голосов
/ 03 октября 2019

У нас есть консольное приложение, которое использует PrintDocument в C # для создания PDF с помощью встроенного принтера «Microsoft Print to PDF» в Windows 10 / Server 2016. Мы используем пакет HPC от Microsoft, поэтому это приложение может запускаться несколько раз наодин и тот же сервер - оба приложения пытаются одновременно печатать на одном принтере. Время от времени один из файлов будет иметь размер 0 байт. Я также могу найти несколько ошибок в журнале событий.

Я попытался удалить все другие принтеры, кроме Microsoft Print to PDF. Я попытался установить различные дополнительные параметры в настройках принтера (например, спулинг - так, чтобы он ожидал, пока последняя страница не будет помещена в буфер).

В нашем коде в настоящее время я проверяю размер файла после того, как считаю, что он должен быть сгенерирован - и если он равен 0 байтам, я повторяю до 3 раз. Это работает, но мне было интересно, есть ли лучшее решение для этого.

Я также пытался изменить уровень изоляции драйвера принтера - но этот параметр был отключен для этого принтера.

Следующий код должен повторить проблему. Перед запуском необходимо открыть «Просмотр событий» и перейти к «Журналы приложений и служб» -> Microsoft -> Windows -> PrintService. Щелкните правой кнопкой мыши на журнале «Оперативный» и выберите «включить» его. Журнал «Администратор» и «Оперативный» будут содержать записи в случае сбоя.

    static class Program
    {
        static void Main()
        {
            var tester = new PrintPdfTest();
            tester.CleanupPrev(@"C:\temp\");
            tester.Run(@"C:\temp\", 5);
        }
    }

    public class PrintPdfTest
    {
        private EventWaitHandle m_waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);

        public void CleanupPrev(string dir)
        {
            foreach (var file in Directory.GetFiles(dir, "file*.pdf"))
                File.Delete(file);
        }

        public void Run(string dir, int nbrOfFiles)
        {
            var threads = new List<Thread>();

            m_waitHandle.Reset();
            for (int i = 0; i < nbrOfFiles; i++)
            {
                var fileName = Path.Combine(dir, $"file{i}.pdf");
                var t = new Thread(ThreadMethod);

                threads.Add(t);
                t.Start(fileName);
            }

            // All threads created -- let them go
            Thread.Sleep(1000);
            m_waitHandle.Set();

            foreach (var thread in threads)
                thread.Join();

            threads.Clear();
            m_waitHandle.Dispose();
            m_waitHandle = null;

            Thread.Sleep(1000);
            for (int i = 0; i < nbrOfFiles; i++)
            {
                var fileName = Path.Combine(dir, $"file{i}.pdf");
                if (File.Exists(fileName))
                {
                    var info = new FileInfo(fileName);
                    System.Diagnostics.Debug.WriteLine($"File {fileName} has size: {info.Length}");
                }
            }

        }

        private void ThreadMethod(object state)
        {
            using (var printDoc = new PrintDocument())
            {
                printDoc.PrintPage += PrintDoc_PrintPage;
                printDoc.DefaultPageSettings.Landscape = true;

                var settings = printDoc.PrinterSettings;
                settings.PrinterName = "Microsoft Print to PDF";
                settings.PrintToFile = true;
                settings.PrintFileName = (string)state;

                m_waitHandle.WaitOne();
                printDoc.Print();
            }
        }

        private void PrintDoc_PrintPage(object sender, PrintPageEventArgs e)
        {
            e.Graphics.DrawString(
                "This is a test",
                new System.Drawing.Font("Arial", 8),
                System.Drawing.Brushes.Black,
                30f, 30f);
        }
    }

После запуска кода найдите в папке C: \ Temp файлы с именем «file * .pdf». - если какой-либо из них имеет размер 0 байт, значит, проблема возникла.

При возникновении проблемы в журнале регистрируются следующие типы событий:

Идентификатор события: 824 Категория задачи: Выполнение фильтров печати в конвейере очереди печати Уровень: ошибка Произошла фатальная ошибка припечать документа задания, идентификатор 6 в очереди печати Microsoft Print to PDF. Процесс конвейера фильтра печати был прерван. Информация об ошибке: 0x88985006.

Код события: 842 Категория задачи: Изоляция драйверов принтера и других подключаемых модулей Уровень: информация Задание печати 6 было отправлено через процессор печати MS_XPS_PROC на принтер Microsoft Печать в PDF, драйвер Microsoft PrintВ PDF, в режиме изоляции 0 (0 - загружен в спулер, 1 - загружен в общую песочницу, 2 - загружен в изолированную песочницу). Код ошибки Win32, возвращенный процессором печати: 0x88985006.

Не удалось напечатать документ Print Document, принадлежащий {username}, на принтере Microsoft Print to PDF. Попробуйте распечатать документ еще раз или перезапустите диспетчер очереди печати. Тип данных: RAW. Размер файла спула в байтах: 80201. Количество напечатанных байтов: 80201. Общее количество страниц в документе: 1. Количество напечатанных страниц: 0. Клиентский компьютер: \ имя_компьютера. Код ошибки Win32, возвращенный процессором печати: 2291683334. Указанный интерфейс уже зарегистрирован.

...