通过 PHP 启动服务器端打印作业

发布于 2024-08-08 23:39:07 字数 955 浏览 6 评论 0原文

这很可能不是一件容易的事,但情况如下:

我编写了一个 C# 命令行应用程序,该应用程序:

  • 使用 ITextSharp 创建 PDF
  • 将其写入磁盘
  • 使用 Acrord32.exe (这是 Acrobat Reader)通过 System.Diagnostics.Process 以静默打印生成的 PDF

如果我构建解决方案并双击 pdfGen.exe,它会按预期工作。 PDF 已创建并打印。

现在,我的应用程序必须部署在运行 IIS 7 的 Windows Vista 内部服务器上。该服务器运行一些 PHP Web 应用程序。它将使用 shell_exec() 通过 PHP 调用,以便生成的 PDF 将在连接到服务器的打印机上打印。

所以我的 PHP 页面基本上是这样的:

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

但这里出了问题。根据任务管理器等发生的情况:

  • pdfGen.exe 启动
  • PDF 创建
  • Acrord32.exe 启动
  • pdfGen.exe 永远挂起(并且PHP 脚本也是如此)并且没有打印任何内容

我很确定这是一些与权限相关的问题。我已经授予 IIS_IUSRS 对默认打印机以及 Acrord32.exe 所在目录的访问权限。但仍然没有打印。但是,如果我手动启动 pdfGen.exe,它就可以工作。

知道我缺少什么吗?

编辑:

我不必使用 Acrobat Reader 来打印 PDF。如果有另一种方法可以静默打印服务器端创建的 PDF,我根本不介意。

This is most likely not an easy one but here is the situation:

I have written a C# command line application which:

  • creates a PDF using ITextSharp
  • writes it to disk
  • uses Acrord32.exe (this is Acrobat Reader) via System.Diagnostics.Process in order to silently print the generated PDF

If I build my solution and double click the pdfGen.exe, it works as expected. The PDF is created and printed.

Now, my app has to be deployed on a internal server with Windows Vista running IIS 7. This server has some PHP webapp running. And it will be called via PHP using shell_exec() so that the resulting PDF will be printed on the printer attached to the server.

So my PHP page looks basically like this:

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

But here things go wrong. What happens is according to task manager etc.:

  • pdfGen.exe starts
  • the PDF is created
  • Acrord32.exe starts
  • pdfGen.exe hangs forever (and so does the PHP script) and nothing is printed

I am pretty sure it is some permission related problem. I already gave IIS_IUSRS access to the default printer, and to the directory where Acrord32.exe is located. But still, no printing. However, if I start my pdfGen.exe manually it works.

Any idea what I am missing?

EDIT:

I am not bound to use Acrobat Reader in order to print the PDF. If there is another way in order to silently print the created PDF serverside, I would not mind at all.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

岁月静好 2024-08-15 23:39:07

为了检查发生了什么,请尝试运行
来自 Sysinternals 的进程监视器并筛选到 adobe acrobat 进程的事件。你会看到acrobat的系统调用,它会让你或多或少地知道出了什么问题。

In order to check what is going on, try to run
the process monitor from Sysinternals and filter the events to the adobe acrobat process. You will see the system calls of acrobat and it will allow you to know more or less what is going wrong.

萌梦深 2024-08-15 23:39:07

我知道您的解决方案有一个小改进:SumatraPDF 有一个很好的命令行界面,可用于在打印后自动关闭 Sumatra。

我使用PHP“system”或“exec”函数执行批处理文件来打开SumatraPDF:(

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

您也可以指定要打印的打印机名称)

I know a small improvement to your solution: SumatraPDF has a nice command-line interface that can be used to auto-close Sumatra after printing.

I used PHP "system" or "exec" functions to execute a batch file to open SumatraPDF:

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

(you can also specify the printer name to print on)

无人问我粥可暖 2024-08-15 23:39:07

这是一个有趣的计划。

IIS_IUSRS
似乎没有打印权限,请尝试将 IIS_IUSRS 添加到打印操作员组/向用户授予打印权限。

that's an interesting program.

IIS_IUSRS
seems to have no permission to print, try adding IIS_IUSRS to Print Operators Group / grant Print permission to the user.

等数载,海棠开 2024-08-15 23:39:07

Shell_exec() 几乎用于 shell 命令(ls/dir、cp 等)
您是否尝试过使用 exec() 而不是 shell_exec() ?

Shell_exec() is almost intended for shell commands (ls/dir, cp, etc.)
Have you tried to use exec() instead of shell_exec() ?

临风闻羌笛 2024-08-15 23:39:07

感谢大家的评论。不幸的是,这个“php start printjob”是一个更大项目的一部分,今天被取消了,因为,嗯……我不知道……政治原因。我猜这个项目几乎已经死了。

不管怎样,我在过去的几天里又尝试了几次,但无法让它与 IIS 一起工作。我已经实现并测试过的解决方案:删除 IIS,使用本地 apache 安装 XAMPP 或 WAMPP 包以及以管理员访问权限运行的 PHP。

这成功了。我在 PHP 中使用了 pclose(popen('...command...', 'r')); 来启动 .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 已启动、打印并且再也没有关闭。因此,每个打印作业都会启动一个新的 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 一起使用,我仍然愿意接受它作为答案。 >

Thanks all for your comments. Unfortunately this "php start printjob" thing was part of a larger project that was cancelled today because of, well... I dont know... political reasons. Guess the project is pretty much dead.

Anyway, I tried myself a few more times in the last days and could not get it to work with IIS. My solution that I implemented and tested already: remove IIS, install a XAMPP or WAMPP package with a local apache and PHP that runs with admin access rights.

This did the trick. I used pclose(popen('...command...', 'r')); in PHP in order to start the .exe and so that PHP does not wait until the PDF is finished. It all worked great.

Here is my C# code which starts the print job using 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();  
}  

The first argument is the path to the PDF that should be printed, the second parameter is the absolute path to the AcroRd32.exe.

The only problem left was that AcroRd32.exe was started, printed and never got closed again. So every printjob started a new instance of AcroRd32.exe (I am using Acrobat Reader 9.0). So if you printed 10 times, 10 acrobat reader instances were created.

What I did was starting the print job, then waiting X seconds, hoping that the printer was finished and then killing all AcroRd32.exe instances:

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;
}

This worked out quite well.


Note that the above (killing all AcroRd32.exe and running PHP with admin privilegs) was only doable because: The whole thing is only used by one user at a time and has a very limited area of use.

It should be used on a touchscreen application deployed at the clients POS. A salesman would use the PHP app in order to configure a product, and then PHP would call my .exe which would create and print a PDF in the background. The printed document is then handed to the client. So security etc. was not really a concern in this case.


If anyone has a solution in order to use it with IIS, I am still willing to accept it as an answer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文