我在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脚本。当我在浏览器中打开新选项卡并浏览同一站点时,它会正确打开。但是一旦请求运行外部控制台应用程序并且此应用程序抛出异常,页面就会再次挂起。
任何帮助都会非常明显。
答案 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代码不是由我完成的,而不是我的逻辑,所以请不要问为什么我这样做。