node.jspowershellexecchild-processread-host

How is child_process.exec('powershell "$userInput = Read-Host;"') handled in node.js?


I am experimenting with the code below, for testing how does child_process.exec() in node.js handle standard input from user.

import { exec } from 'child_process';
exec('powershell "$userInput = Read-Host;"', (err, stdout, stderr) => {
  if(err) throw err;
  console.log(stdout);
  console.log(stderr);
});

When I ran this through node main.js, the terminal is running forever with no output.

It seems that the exec() function creates a new shell waiting for user to type in it. However, I was unable to find the place to do so.

So I wonder if there are some ways to show that place or to handle this problem without the need to use Read-Host to receive user input.


Update: I wonder if I could redirect the user input in the current process(i.e. node.js) to the subprocess(i.e. powershell) as well as the output of subprocess to the current process using exec or any else API.


Solution

  • Assuming that you're asking how to provide stdin input programmatically to a launched child process:

    import { spawn } from 'child_process'
    
    // Note the use of $input to refer to stdin input.
    let ps = spawn(
      'powershell.exe', 
      [
        '-NoProfile', '-Command', 
        '$userInput = $input; "You entered: $userInput"'
      ]
    )
    
    // Connect the child process' output streams to the calling process'
    ps.stdout.pipe(process.stdout)
    ps.stderr.pipe(process.stderr)
    
    // Write the desired input to the child process' stdin.
    ps.stdin.write('user input')
    
    // Close stdin; without this, the child process won't terminate.
    ps.stdin.end()
    

    As you've discovered yourself, if you want to connect the calling process' stdin stream to that of the PowerShell child process, i.e. to relay stdin input received by the current process to the child process, replace the ps.stdin.write('user input') and ps.stdin.end() calls with:

    // Relay the current process' stdin input to the PowerShell child process.
    process.stdin.pipe(ps.stdin)
    

    Note: