Node.js   发布时间:2022-04-24  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了node.js – 从C#调用Edge.js时,如何挂钩stdout和stderr?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
背景

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

方法1

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

如果Edge进程终止,那么通过简单地声明@L_534_0@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);

显然,这仅在Edge代码终止时有效,并且在最坏的情况下msgs可能会变大.但是,它可能表现良好,因为只需要一次编组调用即可获得所有消息.

方法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;
}

我真的可以使用Action,但Edge似乎需要Func< object,Task< object>>,否则它不会代理该函数.然后,在Javascript中,我们可以检测到该函数并像这样使用它:

var func = Edge.Func(@"
    return function(payload,callBACk) {
        if (typeof (payload.stdoutHook) === 'function') {
            process.stdout.write = payload.stdoutHook;
        }

        // do lots of stuff while stdout and stderr are hooked...
        var what = require('whatever');
        what.futz();

        // terminate.
        callBACk(null,result);
}");

dynamic result = func(payload).Result;

问题

Q1.这两种技术似乎都有效,但有没有更好的方法可以做到这一点,内置于Edge的内容可能是我错过了?这两种解决方案都具有侵入性 – 它们需要一些填充码来包装要在Edge中完成的实际工作.这不是世界末日,但如果有一种非侵入性方法会更好.

Q2.在方法2中,我必须在这里返回任务

return Task.FromResult<object>(null);

返回已完成的“空任务”感觉不对.但还有另一种写作方式吗?

Q3.在挂钩stdout和stderr时,我是否需要在Javascript代码中更严格?我注意到在double-edge.js中有这个代码,坦率地说我不确定这里发生了什么,但它比我粗略覆盖process.stdout.write更复杂:-)

// 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; });
    })();
}

解决方法

问题1:在从CLR调用Node时,Edge中没有任何内置功能可以自动捕获Node.js代码的stdout或stderr.在某些时候,我想到编写Edge的扩展,这将使得跨越CLR / V8边界的编组流变得容易.在引擎盖下它将与您的方法2非常相似.它可以作为Edge顶部的独立模块完成.

Q2:在这种情况下,返回完成的任务非常合适.您的函数捕获了Node.js输出,对其进行了处理,并且实际上已经“完成”了.返回使用Null完成的任务实际上是从Action返回的道德等同物.

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

大佬总结

以上是大佬教程为你收集整理的node.js – 从C#调用Edge.js时,如何挂钩stdout和stderr?全部内容,希望文章能够帮你解决node.js – 从C#调用Edge.js时,如何挂钩stdout和stderr?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。