Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to pass stdio to nodejs #163

Open
soroshsabz opened this issue Mar 21, 2023 · 11 comments
Open

How to pass stdio to nodejs #163

soroshsabz opened this issue Mar 21, 2023 · 11 comments

Comments

@soroshsabz
Copy link

soroshsabz commented Mar 21, 2023

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

@soroshsabz
Copy link
Author

I add this question in SO

@soroshsabz
Copy link
Author

@Taritsyn Did you have any idea?

@soroshsabz
Copy link
Author

related to Taritsyn/JavaScriptEngineSwitcher#110

@soroshsabz
Copy link
Author

@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

@JeremyTCD
Copy link
Member

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.

@soroshsabz
Copy link
Author

@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

@JeremyTCD
Copy link
Member

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

@soroshsabz
Copy link
Author

@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

@JeremyTCD
Copy link
Member

JeremyTCD commented Mar 27, 2023

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.

@soroshsabz
Copy link
Author

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?)

@JeremyTCD
Copy link
Member

JeremyTCD commented Mar 27, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants