If all you're looking to do is a one-time call to a function defined inside your PowerShell script, the following should do:
let child = require('child_process').spawn(
'powershell',
[
'-noprofile', '-executionpolicy', 'bypass', '-c',
'. ./powershell-script.ps1; psDoSomething'
],
// In this simple example, pass the child process' output
// streams directly through to this process' output streams.
{ stdio: 'inherit' }
)
The above uses powershell.exe, the Windows PowerShell CLI, with its -c / -Command parameter to process a given snippet of PowerShell code.
Since the function to invoke is defined inside the ./powershell-script.ps1 script, that script must be dot-sourced in order to load the function definition into the caller's scope.
Thereafter, the function can be invoked.
If you're looking to spawn a PowerShell child process to which you can iteratively feed commands for execution later, on demand, via stdin - in other words: to create a programmatically controlled REPL - you'll need a solution whose fundamentals are outlined in Zac Anger's answer, based on spawning the PowerShell child process with -c - (-Command -), namely as powershell.exe -noprofile -executionpolicy bypass -c -
- Caveat: Sending a command spanning multiple lines must be terminated with two newlines; see GitHub issue #3223 for details.
let child = require('child_process').spawn(
// Start PowerShell in REPL mode, with -c - (-Command -)
'powershell',
[
'-noprofile', '-executionpolicy', 'bypass', '-c',
'-' // Start PowerShell as a REPL
]
)
// Connect the child process' output streams to the calling process',
// so they are *passed through*.
// Note: Using { stdio: 'inherit' } in the .spawn() call instead
// would prevent using child.stdin.write() below.
child.stdout.pipe(process.stdout)
child.stderr.pipe(process.stderr)
// Dot-source the file that defines the function.
// Note the double \n to ensure that PowerShell recognizes the end of the command.
child.stdin.write('. ./powershell-script.ps1\n\n')
// Now you can invoke it.
child.stdin.write('psDoSomething\n\n')
// ... pass additional commands, as needed.
// End the session.
child.stdin.write('"Goödbyə!"\n\n')
child.stdin.end()
Character-encoding note:
child.stdin.write() sends UTF-8-encoded strings by default (you can change the encoding with child.stdin.setEncoding(), as shown in Zac's anwer).
For PowerShell on Windows to interpret UTF-8-encodes string correctly and to
also make it output UTF-8 itself, the current console's code page must be 65001 beforehand - run chcp to verify. If it isn't:
If your Node.js program runs from a cmd.exe session, run the following first:
chcp 65001
If it runs from a PowerShell session, run the following first:
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [Text.UTF8encoding]::new()
On Unix-like platforms, PowerShell fortunately defaults to UTF-8.