2

我正在使用 c# 启动一个进程(实际上是 phantomjs),并尝试通过标准输出传递信息(base64image 字符串)。如果该过程成功,则一切顺利。如果进程失败(在这种情况下,因为 phantomjs 正在打开的页面中存在 javascript 错误),它会无限期挂起。

我的代码如下所示:

var path = Server.MapPath("phantomjs.exe");
var args = string.Join(" ", new[] { Server.MapPath(@"screenshot.js"), url });

var info = new ProcessStartInfo(path, args);
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
info.CreateNoWindow = true;

var p = Process.Start(info);

// it hangs on the following line:
var base64image = p.StandardOutput.ReadToEnd();
bytes = Convert.FromBase64CharArray(base64image.ToCharArray(), 0, base64image.Length);

我假设运行任何外部进程都可能导致这个问题。如果该过程没有正确完成(无论出于何种原因),那么将永远不会有一个输出端可供读取(也许?)。

我想知道的是,如何引入最大超时?如果该过程成功并在小于超时时间内退出,那就太好了。如果没有,请终止该进程并执行其他操作。

我尝试了以下方法:

if (p.WaitForExit(30000))
{
    var base64image = p.StandardOutput.ReadToEnd();
    bytes = Convert.FromBase64CharArray(base64image.ToCharArray(), 0, base64image.Length);

    // do stuff with bytes
}
else
{
    p.Kill();

    // do something else
}

这在我运行一个更简单的应用程序时起作用(它只是在 60 秒内每秒向控制台写入一个数字)。当我尝试使用 phantomjs 时,它会失败(等待 30 秒)对于应该工作的情况(当我恢复到我的原始代码或从控制台运行它时需要不到 30 秒)。

可能phantomjs(或者我写的js脚本)没有正常退出,但是c#能处理所有场景吗?

4

1 回答 1

1

您必须在脚本中添加一个全局错误处理程序。当出现 JavaScript 执行错误(解析,异常,...)时,phantomjs 不会自行退出。在一个简单的脚本中自己尝试。

此处提供了一个非常基本的示例。

phantom.onError = function(msg, trace) {
    var msgStack = ['PHANTOM ERROR: ' + msg];
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + (t.file || t.sourceURL) + ': ' + t.line + (t.function ? ' (in function ' + t.function + ')' : ''));
        });
    }
    console.error(msgStack.join('\n'));
    phantom.exit(1);
};

此外还可以添加页面错误处理程序

page.onError = function(msg, trace) {
    var msgStack = ['ERROR: ' + msg];
    if (trace && trace.length) {
        msgStack.push('TRACE:');
        trace.forEach(function(t) {
            msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function + '")' : ''));
        });
    }
    console.error(msgStack.join('\n'));
};

请注意,当WebPage#onError 处理程序未捕获到JavaScript 执行错误时,将调用 phantom.error 。

于 2013-06-20T08:11:33.760 回答