Запуск серверной печати через PHP - PullRequest
4 голосов
/ 30 октября 2009

Скорее всего, это не легко, но вот ситуация:

Я написал приложение для командной строки C #, которое:

  • создает PDF с помощью ITextSharp
  • записывает на диск
  • использует Acrord32.exe (это Acrobat Reader) через System.Diagnostics.Process для автоматической печати сгенерированного PDF

Если я создаю свое решение и дважды щелкаю pdfGen.exe, оно работает как положено. PDF создан и напечатан.

Теперь мое приложение должно быть развернуто на внутреннем сервере с Windows Vista под управлением IIS 7. На этом сервере запущено некоторое веб-приложение PHP. И он будет вызываться через PHP с использованием shell_exec(), поэтому полученный PDF-файл будет напечатан на принтере, подключенном к серверу.

Итак, моя страница PHP выглядит примерно так:

shell_exec('/path/to/pdfGen.exe');

Но здесь все идет не так. Что происходит в соответствии с менеджером задач и т. Д.:

  • pdfGen.exe начинается
  • PDF создан
  • Acrord32.exe запускается
  • pdfGen.exe зависает навсегда (как и скрипт PHP) и ничего не печатается

Я почти уверен, что это какая-то проблема, связанная с разрешениями . Я уже дал IIS_IUSRS доступ к принтеру по умолчанию и к каталогу, в котором находится Acrord32.exe. Но все равно, нет печати. Однако, если я запускаю свой pdfGen.exe вручную, он работает.

Есть идеи, что мне не хватает?

EDIT:

Я не обязан использовать Acrobat Reader для печати PDF. Если есть другой способ, чтобы молча распечатать созданный сервер PDF, я бы не стал возражать.

Ответы [ 5 ]

1 голос
/ 06 марта 2011

Я знаю небольшое улучшение вашего решения: SumatraPDF имеет приятный интерфейс командной строки, который можно использовать для автоматического закрытия Sumatra после печати. ​​

Я использовал PHP "системные" или "exec" функции для выполнения командного файла, чтобы открыть SumatraPDF:

sumatrapdf.exe -print-to-default -exit-on-print <path_to_PDF_file>

(вы также можете указать имя принтера для печати)

1 голос
/ 03 ноября 2009

Чтобы проверить, что происходит, попробуйте запустить монитор процесса от Sysinternals и фильтрация событий для процесса Adobe Acrobat. Вы увидите системные вызовы acrobat, и это позволит вам более или менее узнать, что происходит не так.

0 голосов
/ 04 ноября 2009

Спасибо всем за ваши комментарии. К сожалению, эта вещь "php start printjob" была частью более крупного проекта, который был отменен сегодня из-за ... ну, я не знаю ... политических причин. Угадай, проект в значительной степени мертв.

В любом случае, я пробовал себя еще несколько раз в последние дни и не смог заставить его работать с IIS. Мое решение, которое я уже внедрил и протестировал: удалите IIS, установите пакет XAMPP или WAMPP с локальным apache и PHP, который работает с правами доступа администратора .

Это добилось цели. Я использовал pclose(popen('...command...', 'r')); в PHP, чтобы запустить .exe и чтобы PHP не ждал, пока закончится PDF. Все работало отлично.

Вот мой код C #, который запускает задание печати с помощью Acrobat Reader

public void Print(string pathname, string acrobatDirectory)
{
    var proc = new Process
    {
        StartInfo =
        {
            Arguments               = String.Format("/t \"{0}\"", pathname),
            FileName                = acrobatDirectory,
            UseShellExecute         = false,
            CreateNoWindow          = true,
            RedirectStandardOutput  = false,
            RedirectStandardError   = false,
        }
    };

    proc.Start();  
}  

Первый аргумент - это путь к PDF, который должен быть напечатан, второй параметр - это абсолютный путь к AcroRd32.exe.

Единственной проблемой оставалось то, что AcroRd32.exe был запущен, напечатан и больше никогда не закрывался. Так что каждый printjob запускал новый экземпляр AcroRd32.exe (я использую Acrobat Reader 9.0). Поэтому, если вы напечатали 10 раз, было создано 10 экземпляров Acrobat Reader.

Я запустил задание на печать, затем подождал X секунд, надеясь, что принтер был завершен, и затем уничтожил все AcroRd32.exe экземпляров:

public void Print(string pathname, string acrobatDirectory)
{
    Debug.WriteLine("Printing...");

    Printer.Print(pathname, acrobatDirectory);

    Thread.Sleep(30000);

    try
    {
        Debug.WriteLine("Trying to kill runnung AcroRd32.exe's ");

        FindAndKillProcess("AcroRd32");
    }
    catch (Exception)
    {
        Debug.WriteLine("AcroRd32.exe could not be killed...");
    }
}

private bool FindAndKillProcess(string name)
{
    foreach (Process clsProcess in Process.GetProcesses())
    {
        if (clsProcess.ProcessName.StartsWith(name))
        {
            clsProcess.Kill();
            return true;
        }
    }

    return false;
}

Это сработало довольно хорошо.

<ч />

Обратите внимание, что вышеописанное (уничтожение всех AcroRd32.exe и запуск PHP с правами администратора) было выполнимо только потому, что: Все это используется только одним пользователем одновременно и имеет очень ограниченную область использования .

Его следует использовать в приложении с сенсорным экраном, развернутом в POS-клиенте. Продавец использовал приложение PHP для настройки продукта, а затем PHP вызывал мой .exe, который создавал и печатал PDF в фоновом режиме. Затем распечатанный документ передается клиенту. Таким образом, безопасность и т. Д. На самом деле не были проблемой в этом случае.

<ч />

Если у кого-то есть решение для использования его с IIS, я все равно готов принять его в качестве ответа.

0 голосов
/ 02 ноября 2009

Shell_exec () почти предназначен для команд оболочки (ls / dir, cp и т. Д.) Вы пытались использовать exec () вместо shell_exec ()?

0 голосов
/ 30 октября 2009

это интересная программа.

IIS_IUSRS У вас нет разрешения на печать, попробуйте добавить IIS_IUSRS в группу операторов печати / предоставить пользователю разрешение на печать.

...