Ich arbeite an einem C# -Programm, das derzeit Node über Process.Start() ausführt. Ich fange das stdout und stderr von diesem Kindprozess ein und leite es aus meinen eigenen Gründen um. Ich bin dabei, den Aufruf von Node.exe durch einen Aufruf von Edge.js zu ersetzen. Um dies tun zu können, muss ich in der Lage sein, stdout und stderr zuverlässig aus dem in Edge ausgeführten Javascript zu erfassen und die Nachrichten in meine C# -Anwendung zurück zu bekommen.Wenn Sie Edge.js von C# aufrufen, wie hookst du stdout und stderr?
Ansatz 1
ich diesen Ansatz für Vollständigkeit, falls jemand beschreiben werde empfiehlt es :)
Wenn der Edge-Prozess beendet wird, ist es ziemlich einfach ist, sich damit zu befassen, indem einfach ein msgs
Array deklarieren und Überschreiben process.stdout.write
und process.stderr.write
mit neuen Funktionen, die Nachrichten auf diesem Array ansammeln, dann am Ende, einfach die msgs
Array zurückgeben. Beispiel:
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);
Offensichtlich funktioniert das nur, wenn der Edge-Code beendet wird, und Nachrichten können im ungünstigsten Fall groß werden. Es ist jedoch wahrscheinlich eine gute Leistung, da nur ein Marshalling-Aufruf erforderlich ist, um alle Nachrichten zurück zu erhalten.
Ansatz 2
Dies ist ein wenig schwieriger zu erklären. Statt Nachrichten zu sammeln, "haken" wir stdout und stderr mit einem Delegaten, den wir von C# senden. In der C# erstellen wir ein Objekt, das wir in Rand passieren, und das Objekt eine Eigenschaft hat stdoutHook
genannt:
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;
}
Ich konnte wirklich mit einer Aktion weg, aber Rand erscheint die Func<object, Task<object>>
zu verlangen, es gewann Die Funktion sonst nicht übernehmen. Dann wird in der Javascript, können wir diese Funktion und verwenden Sie es wie folgt ermitteln:
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;
Fragen
Q1. Beide Techniken scheinen zu funktionieren, aber gibt es einen besseren Weg dies zu tun, etwas, das Edge vielleicht eingebaut hat, das ich verpasst habe? Beide Lösungen sind invasiv - sie benötigen etwas Shim-Code, um die eigentliche Arbeit, die in Edge erledigt werden soll, einzubinden. Dies ist nicht das Ende der Welt, aber es wäre besser, wenn es eine nicht-invasive Methode gäbe.
Q2. In Ansatz 2, wo ich hier eine Aufgabe zurückkehren
return Task.FromResult<object>(null);
es fühlt sich falsch an eine bereits abgeschlossen „null Aufgabe“ zu sein, zurück. Aber gibt es eine andere Möglichkeit, dies zu schreiben?
Q3. Muss ich im Javascript-Code rigoroser sein, wenn ich stdout und stderr einhänge? Ich stelle fest, in zwei edge.js gibt dieser Code ist, ehrlich gesagt ich bin nicht sicher, was hier passiert, aber es ist ein bisschen komplexer als meine rohe Überschreibung von 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; });
})();
}
Danke Tomasz, also im Grunde Approach 2 mit Augenmerk auf Codierung ist meine beste Wette für jetzt. Es wäre großartig, wenn es einen einfacheren Weg dazu gäbe, vielleicht eine Überladung der Edge.Func(), die ein Paar von optionalen Streams oder Delegaten nehmen kann. –