【问题标题】:Starting serverside print job via PHP通过 PHP 启动服务器端打印作业
【发布时间】:2009-10-30 07:02:12
【问题描述】:

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

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

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

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

现在,我的应用程序必须部署在运行 IIS 7 的 Windows Vista 的内部服务器上。该服务器运行了一些 PHP webapp。它将通过 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,它就可以工作。

知道我错过了什么吗?

编辑:

我不一定要使用 Acrobat Reader 来打印 PDF。如果有其他方法可以静默打印创建的 PDF 服务器端,我完全不介意。

【问题讨论】:

    标签: c# php windows acrobat


    【解决方案1】:

    为了检查发生了什么,请尝试运行 process monitor from Sysinternals 并将事件过滤到 adobe acrobat 进程。你会看到 acrobat 的系统调用,它会让你或多或少知道哪里出了问题。

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

        这是一个有趣的程序。

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

        【讨论】:

        • IIS_IUSRS 是运行 PHP 脚本的用户
        【解决方案4】:

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

        【讨论】:

        • 是的,我试了一下 exec,我也用过 pclose(popen('...command...', 'r'));
        【解决方案5】:

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

        无论如何,最近几天我又尝试了几次,但无法让它与 IIS 一起工作。我已经实现和测试的解决方案:删除 IIS,安装带有本地 apache 和 PHP 的 XAMPP 或 WAMPP 包,该包以 admin 访问权限 运行。

        这成功了。我在 PHP 中使用了pclose(popen('...command...', 'r')); 来启动.exe,这样 PHP 就不会等到 PDF 完成。这一切都很好。

        这是我使用 Acrobat Reader 启动打印作业的 C# 代码

        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 一起使用,我仍然愿意接受它作为答案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-04
          • 2017-08-06
          • 1970-01-01
          相关资源
          最近更新 更多