Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 从C#调用Edge.js时,如何钩住stdout和stderr? 背景_Node.js_Async Await_Task Parallel Library_Stdout_Edge.js - Fatal编程技术网

Node.js 从C#调用Edge.js时,如何钩住stdout和stderr? 背景

Node.js 从C#调用Edge.js时,如何钩住stdout和stderr? 背景,node.js,async-await,task-parallel-library,stdout,edge.js,Node.js,Async Await,Task Parallel Library,Stdout,Edge.js,我正在开发一个C#程序,该程序当前通过Process.Start()运行Node。我从这个子进程捕获stdout和stderr,并出于我自己的原因重定向它。我正在考虑用对Edge.js的调用来代替对Node.exe的调用。为了能够做到这一点,我必须能够可靠地从Edge中运行的Javascript中捕获stdout和stderr,并将消息返回到我的C#应用程序中 方法1 我将描述这种方法的完整性,以防有人推荐:) 如果边缘进程终止,则通过简单地声明msgs数组并覆盖process.stdout.w

我正在开发一个C#程序,该程序当前通过Process.Start()运行Node。我从这个子进程捕获stdout和stderr,并出于我自己的原因重定向它。我正在考虑用对Edge.js的调用来代替对Node.exe的调用。为了能够做到这一点,我必须能够可靠地从Edge中运行的Javascript中捕获stdout和stderr,并将消息返回到我的C#应用程序中

方法1 我将描述这种方法的完整性,以防有人推荐:)

如果边缘进程终止,则通过简单地声明
msgs
数组并覆盖
process.stdout.write
process.stderr.write
以及在该数组上累积消息的新函数来处理这一问题相当容易,然后在结束时,只需返回
msgs
数组。例如:

var msgs = [];
process.stdout.write = function (string) {
    msgs.push({ stream: 'o', message : string });
};
process.stderr.write = function (string) {
    msgs.push({ stream: 'e', message: string });
};

// Return to caller.
var result = { messages: msgs; ...other stuff... };
callback(null, result);
显然,这仅在边缘代码终止时有效,并且在最坏的情况下,MSG可能会变大。但是,它可能会执行得很好,因为只需要一个编组调用就可以返回所有消息

方法2 这有点难以解释。我们使用从C#发送的委托“钩住”stdout和stderr,而不是累积消息。在C#中,我们创建了一个将传递到Edge的对象,该对象有一个名为
stdoutHook

dynamic payload = new ExpandoObject();
payload.stdoutHook = GetStdoutHook();

public Func<object, Task<object>> GetStdoutHook()
{
    Func<object, Task<object>> hook = (message) =>
    {
        TheLogger.LogMessage((message as string).Trim());
        return Task.FromResult<object>(null);
    };

    return hook;
}
问题 问题1。这两种技术似乎都有效,但是否有更好的方法来实现这一点,一些内置到Edge中的东西,也许我已经错过了?这两种解决方案都是侵入性的——它们需要一些垫片代码来包装将在Edge中完成的实际工作。这不是世界末日,但如果有一种非侵入性的方法会更好

问题2。在方法2中,我必须在这里返回一个任务

return Task.FromResult<object>(null);

问题1:Edge中没有内置任何东西可以在从CLR调用Node时自动捕获Node.js代码的stdout或stderr。在某个时候,我考虑编写一个Edge扩展,使跨CLR/V8边界封送流变得容易。在引擎盖下,这将非常类似于你的方法2。它可以作为Edge顶部的独立模块完成

问题2:在这种情况下,返回已完成的任务非常合适。您的函数已经捕获了Node.js输出,并对其进行了处理,实际上已经“完成”了。返回一个用Null完成的任务实际上相当于从一个动作返回


问题3:您所指的代码仅与Windows GUI应用程序相关,而与控制台应用程序无关。如果您正在编写控制台应用程序,只需在传递给Edge.js的Node.js代码级别重写
write
就足够了。注意,
write
in节点的签名允许一个可选的。在方法1和2中,您似乎都忽略了它。特别是在方法2中,我建议将C#callback的JavaScript代理包装到一个JavaScript函数中,该函数在将其分配给
process.stdout.write
之前规范化参数。否则,Edge.js代码可能会假定传递给
write
调用的
encoding
参数是遵循Edge.js调用约定的回调函数

多亏了Tomasz,所以从根本上说,关注编码的方法2是我目前最好的选择。如果有一种更简单的方法来实现这一点,那就太好了,可能是Edge.Func()的重载,它可以接受一对可选的流或委托。
return Task.FromResult<object>(null);
// Fix #176 for GUI applications on Windows
try {
    var stdout = process.stdout;
}
catch (e) {
    // This is a Windows GUI application without stdout and stderr defined.
    // Define process.stdout and process.stderr so that all output is discarded. 
    (function () {
        var stream = require('stream');
        var NullStream = function (o) {
            stream.Writable.call(this);
            this._write = function (c, e, cb) { cb && cb(); };
        }
        require('util').inherits(NullStream, stream.Writable);
        var nullStream = new NullStream();
        process.__defineGetter__('stdout', function () { return nullStream; });
        process.__defineGetter__('stderr', function () { return nullStream; });
    })();
}