4

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

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

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

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

现在,我的应用程序必须部署在运行 IIS 7 的 Windows Vista 的内部服务器上。该服务器运行了一些 PHP webapp。它将通过 PHP using 调用,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 服务器端,我一点也不介意。

4

5 回答 5

1

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

于 2009-11-03T19:05:31.723 回答
1

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

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

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

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

于 2011-03-06T11:52:52.300 回答
0

这是一个有趣的程序。

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

于 2009-10-30T07:11:41.497 回答
0

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

于 2009-11-02T13:12:21.237 回答
0

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

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

这成功了。我pclose(popen('...command...', 'r'));在 PHP 中使用以启动.exeand 以便 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 一起使用,我仍然愿意接受它作为答案。

于 2009-11-04T11:03:00.890 回答