How to pass stdio to nodejs
ITNOA
I want to link my stdio from C# Console Application to NodeJs, to better describe my question, I create a sample like below
I have some code like below
IJsEngine engine = new NodeJsEngine(new NodeSettings { UseBuiltinLibrary = true});
engine.ExecuteFile("SpawnServer.js");
and my SpawnServer.js is like below
const { spawn } = require("child_process");
console.log('Hi');
process.stdout.write("Hi");
spawn("npx", ["ansible-language-server"].concat(" --stdio"), { stdio: 'inherit' });
I like to see Hi in my C# Console Application, But I do not know, How to do it?
Note: All code is in https://github.com/soroshsabz/visualstudio-ansible/tree/features/4-support-ansible-language-server
thanks
I add this question in SO
@Taritsyn Did you have any idea?
related to https://github.com/Taritsyn/JavaScriptEngineSwitcher/issues/110
@JeremyTCD Did you have any Idea? or if this library does not support this, Did you have any advice to how to add this feature? maybe I can provide PR for this
Hey apologies for the slow response, I'm not sure how to pipe output when using JavaScriptEngineSwitcher, but if you use this library directly, you can do it like this:
using Jering.Javascript.NodeJS;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace Example.Logging
{
internal class Program
{
static async Task Main(string[] _)
{
// Prepare DI services
var serviceCollection = new ServiceCollection();
serviceCollection.AddNodeJS();
serviceCollection.AddLogging((ILoggingBuilder loggingBuilder) =>
{
loggingBuilder.AddConsole();
});
// Get INodeJSService
IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider();
INodeJSService nodeJSService = serviceProvider.GetRequiredService<INodeJSService>();
// Invoke js
await nodeJSService.InvokeFromStringAsync(@"module.exports = (callback) => {
console.log('Hello world!');
callback(null);
}").ConfigureAwait(false);
}
}
}
Your project will have to reference the Jering.Javascript.NodeJS and Microsoft.Extensions.Logging.Console packages.
You will get output like:
info: Jering.Javascript.NodeJS.HttpNodeJSService[0]
Connected to NodeJS through HTTP/1.1. Endpoint: http://[::1]:62220/.
info: Jering.Javascript.NodeJS.HttpNodeJSService[0]
Connected to NodeJS process: 11960.
info: System.Net.Http.HttpClient.IHttpClientService.LogicalHandler[100]
Start processing HTTP request POST http://[::1]:62220/
info: System.Net.Http.HttpClient.IHttpClientService.ClientHandler[100]
Sending HTTP request POST http://[::1]:62220/
info: Jering.Javascript.NodeJS.HttpNodeJSService[0]
Hello world!
info: System.Net.Http.HttpClient.IHttpClientService.ClientHandler[101]
Received HTTP response headers after 101.8191ms - 200
info: System.Net.Http.HttpClient.IHttpClientService.LogicalHandler[101]
End processing HTTP request after 108.5691ms - 200
You can filter output by following Microsoft's instructions here.
Let me know if you have any issues.
@JeremyTCD are you sure, this method, redirect standard I/O to/from NodeJS, for example, what is happen, if I run below code in the NodeJS
const stdin = process.openStdin()
process.stdout.write('Enter name: ')
stdin.addListener('data', text => {
const name = text.toString().trim()
console.log('Your name is: ' + name)
stdin.pause() // stop reading
})
Are you sure, nodeJs get input from my standard input?
thanks
Ah it does not.
I assumed from your "hi" example that you just needed output, stdin is not piped from .Net to Node.js.
Would an invocation work? E.g.
string? data = Console.ReadLine();
nodeJSService.InvokeFromStringAsync(..., args: new object?[] { data });
@JeremyTCD No, I want to bind (redirect) all input and output together, from/to .Net Node.js. for example, I have console application in Node.JS and I want when run this app in .Net, user can seamless using this app.
thanks
Options:
- Use invocations to "pipe" input to the Node.js process.
- Register a custom service for INodeJSProcessFactory that pipes input to the Node.js process.
I do not understand, did you can provide some example? (If I understand correctly, you says Jering can support redirection both standard output and input? correct?)
Piping input to Node.js processes is not supported out-of-the-box. But there are ways to implement such behaviour.
For the first option, read input and pass it to the Node.js process using invocations, like in this comment.
As for the second option, replace the INodeJSProcessFactory service that creates Node.js processes with a custom one that pipes input to them. Replacement of the service is done using standard Microsoft DI patterns. You can use the existing service to get started on your custom implementation. Microsoft has an example on piping to a process' stdin.