Node JS如何在派生子进程(powershell脚本)中调用函数?



是否有一种方法可以从父节点js脚本中调用派生子进程中的函数,即powershell脚本?

节点脚本:

const cp = require("child_process");
const psData = cp.spawn
("powershell -executionpolicy bypass  ./powershell-script.ps1", [], {
shell: "powershell.exe",
});

powershell脚本:

function psDoSomething{
# do something
}

Node没有内置的方式来调用子进程中的特定函数。如果有帮助的话,您可以将参数传递给PS脚本,或者您可以生成/执行另一个PS脚本,但是Node不知道或不关心Powershell(或Python、Shell或生成/执行脚本中的任何其他语言)。如果你需要这个功能,你可以在NPM上尝试一个与powershell相关的包。

编辑:OP在评论中建议使用stdin.write对子进程,并在子进程中收听STDIN,这是一个有趣的想法。我不使用Powershell,但下面是使用Bash的工作方式:

const bashSession = require('child_process').spawn('./foo.sh')
bashSession.stdin.setEncoding('utf-8')
bashSession.stdout.pipe(process.stdout)
bashSession.stdin.write('someFuncn')
bashSession.stdin.end()
#!/bin/bash
doThing() {
echo We made it here
}
while read line; do
if [[ $line == someFunc ]]; then
doThing
else
echo "$line"
fi
done < "${1:-/dev/stdin}"

让子进程监听stdin上的所有内容可能会产生问题,但同样的概念也可以用于指定文件或TCP套接字。

如果你想做的是一个一次性调用到你的PowerShell脚本中定义的函数,应该这样做:

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' }
)
  • 上面使用powershell.exe, Windows PowerShell命令行,与它的-c/-Command参数来处理一个给定的PowerShell代码片段。

  • 由于要调用的函数是在./powershell-script.ps1脚本中定义的,因此该脚本必须是点源的,以便将函数定义加载到调用者的作用域中。

  • 之后可以调用函数


如果您希望生成一个PowerShell子进程,您可以根据需要通过stdin迭代地提供命令以供稍后执行-换句话说:创建一个可编程控制的 REPL-你需要一个解决方案,其基本原理在Zac Anger的回答中概述,基于生成的PowerShell子进程与-c -(-Command -),即powershell.exe -noprofile -executionpolicy bypass -c -

  • 警告:发送跨越多行的命令必须以两个换行符结束;有关详细信息,请参阅GitHub issue #3223。
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.ps1nn')
// Now you can invoke it. 
child.stdin.write('psDoSomethingnn')
// ... pass additional commands, as needed.
// End the session.
child.stdin.write('"Goödbyə!"nn')
child.stdin.end()

字符编码注意:

  • child.stdin.write()默认发送utf -8编码的字符串(您可以使用child.stdin.setEncoding()更改编码,如Zac的回答所示)。

  • Windows上的PowerShell可以正确地解释utf -8编码字符串也使它本身输出UTF-8,当前控制台的代码页必须是65001之前-运行chcp来验证。如果不是:

    • 如果您的Node.js程序从cmd.exe会话运行,请先运行以下命令:

      chcp 65001 
      
    • 如果在PowerShell会话中运行,请先执行以下命令:

      $OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = [Text.UTF8encoding]::new()
      
  • 在Unix类平台上,PowerShell幸运地将默认为UTF-8。

最新更新