如果通过Wscript.shell调用的外部应用程序抛出异常,PHP脚本将挂起

时间:2013-10-30 04:12:15

标签: c# php apache

我在C#中使用以下PHP代码调用控制台应用程序TPDF.exe

<?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#应用程序源代码进行一些调整?

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

修改

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

任何帮助都会非常明显。

2 个答案:

答案 0 :(得分:3)

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

我假设您正在创建一个PDF文件,可以选择自定义解决方案:

任何理由不使用这些?

接下来,更多针对您的问题。

最明显的是,您设置$oShellLink->WindowStyle = 1;,其中1表示:

  

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

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

  

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

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

关于这些:

  • <强> .Run(strCommand, intWindowStyle, bWaitOnReturn)

      

    在新流程中运行程序。 - .Run on msdn

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

  • .Exec(strCommand)

      

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

    只需要一个参数,即命令,然后返回一个具有整洁属性的对象,使您可以比.Run()更好地控制命令行执行过程。
    这对于像你这样的命令行脚本更有用。它还会打开stdErr等,因此您可以进行更多调试。

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

另请注意,在使用.Run()的命令行运行命令行应用程序时,您可能需要使用%comspec% /c [script]在命令提示符窗口中运行应用程序,可以通过设置{{1到0。

答案 1 :(得分:1)

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

P.S。 PHP代码不是由我完成的,而不是我的逻辑,所以请不要问为什么我这样做。