2

我正在调用控制台应用程序,TPDF.exe它是用 C# 制作的,带有以下 PHP 代码。

<?php   
    $myFile=".."; // This variable holds the xml contents 
    $folder=dirname(__FILE__);
    $exe=dirname(dirname(__FILE__))."\\pdfexe\\TPDF.exe";
    $args="\"\"$folder\\$outputfilename\"\" \"\"$folder\\$myFile\"\"";

    $WshShell = new COM("WScript.Shell");
    $oShellLink = $WshShell->CreateShortcut("$folder\\temp.lnk");
    $oShellLink->TargetPath = $exe;
    $oShellLink->Arguments = $args;
    $oShellLink->WorkingDirectory = dirname($exe);
    $oShellLink->WindowStyle = 1;
    $oShellLink->Save();
    $oExec = $WshShell->Run("$folder\\temp.lnk", 0, false);
    //$WshShell->Quit();
    $WshShell=null;
    $oShellLink=null;
    $oExec=null;
    unset($WshShell,$oShellLink,$oExec);
    unlink("$folder\\temp.lnk");
?>

一切正常。但我面临的问题是,如果应用程序TPDF.exe抛出异常(我已经捕获并记录),它会使 Apache 服务器无响应,实际上它会挂起 APACHE。我必须停止并重新启动 APACHE 才能使其再次工作。

那么避免这个问题的可行解决方案是什么?可能我必须对上面的 PHP 代码或 c# 应用程序源代码进行一些调整?

PS我没有在这里发布C#代码,因为它工作正常,唯一的问题是当应用程序抛出异常时apache被挂起。

编辑:

实际上,它不是挂起的 Apache 服务器,而是挂起的 PHP 脚本。当我在浏览器中打开新标签并浏览同一站点时,它会正确打开。但是,一旦请求运行外部控制台应用程序并且该应用程序抛出异常,页面就会再次挂起。

任何帮助都将是非常可观的。

4

2 回答 2

3

为什么使用 WShell?PHP 具有用于执行外部应用程序的内置命令。这是一个可行的选择,还是您有特定的理由不这样做?如果是这样,如果你能分享这个原因,也许有人可以帮助你以完全不同的方式实现你的目标。

我假设您正在创建一个 PDF 文件,有自定义解决方案的替代方案:

有什么理由不使用这些吗?

接下来,更针对你的问题。

最明显的是,您似乎在设置$oShellLink->WindowStyle = 1;1 的含义:

激活并显示一个窗口。如果窗口被最小化或最大化,系统会将其恢复到原来的大小和位置。应用程序应在第一次显示窗口时指定此标志。

我认为这不是您要寻找的,因为您似乎正在执行命令行。而是将其设置为$oShellLink->WindowStyle = 0;

隐藏窗口并激活另一个窗口。

我对 WShell.Run 和 WShell.Exec 有一些不好的经历,它是一堆热气腾腾的东西,你不应该用棍子从远处触摸,但无论如何,它就在这里..

关于这些:

  • .Run(strCommand, intWindowStyle, bWaitOnReturn)

    在新进程中运行程序。- .在 msdn 上运行

    它需要两个对命令行执行似乎更有意义的参数,intWindowStyle(让我们隐藏窗口..)和 bWaitOnReturn(PHP 是一种顺序执行的语言,所以我们也想按顺序执行,对吗?不是真的..)。

  • .Exec(strCommand)

    Exec 方法返回一个 WshScriptExec 对象,该对象提供有关使用 Exec 运行的脚本的状态和错误信息,以及对StdIn、StdOut 和 StdErr 通道的访问。Exec 方法只允许执行命令行应用程序。Exec 方法不能用于运行远程脚本。不要将 Exec 方法与(WshRemote 对象的)Execute 方法混淆。- msdn 上的 .Exec

    它只需要 1 个参数,即命令,然后返回一个具有简洁属性的对象,使您可以比.Run().
    这似乎对像你这样的命令行脚本更有用。它还打开了 stdErr 等,因此您可以进行更多调试。

试试.Exec()我认为它至少会让你更接近你的问题的答案(因为有更好的调试方法)。您将需要创建一个带有睡眠功能的循环,以便您可以等待进程完成,这样您就可以轻松实现超时并定期检查 stdErr 等,它使您的应用程序更具响应性和更可靠。

另请注意,当您从命令行运行命令行应用程序时,.Run()可能需要使用%comspec% /c [script]在命令提示符窗口中运行应用程序,可以通过设置intWindowStyle为 0 来隐藏它。

于 2013-11-06T10:21:15.067 回答
1

无论如何,我找到了罪魁祸首。控制台应用程序在完成操作后创建一个空白文本文件……PHP 文件检查该文件是否存在。除非该文件存在,否则使用 sleep 函数暂停 php 脚本。由于控制台应用程序因异常而中断,因此没有创建文件,PHP 代码进入无限循环,最终挂起脚本。

PS php代码不是我做的,不是我的逻辑,所以请不要问我为什么这样做。

于 2013-11-06T11:14:36.760 回答