Node.js + Powershell:如何在使用stdin.write时编码Unicode字符

3
这个问题与这个问题相关:Powershell:如何执行包含Unicode字符的路径的命令? 我有一个使用Powershell 5.1生成单个子进程并重复使用它以运行不同命令的Node.js应用程序,因为这比生成单独的进程更快。
问题是,包含Unicode字符的命令会默默失败。
let childProcess = require('child_process')
let testProcess = childProcess.spawn('powershell', [])
testProcess.stdin.setEncoding('utf-8')

testProcess.stdout.on('data', (data) => {
  console.log(data.toString())
})

testProcess.stdout.on('error', (error) => {
  console.log(error)
})

// This path is working, I get command output in the console:
// testProcess.stdin.write("(Get-Acl 'E:/test.txt').access\n");

// This path is not working. I get nothing in the console
testProcess.stdin.write("(Get-Acl 'E:/test .txt').access\n");

编辑 #1

在将命令发送到 Powershell 并将其转换为 System.Char 之前,我已经尝试在 Node.js 端对路径进行 UTF-8 编码:

const path = 'E:/test $([char]0x1f4da).txt'
const command = `Get-Acl $(${path}).access`
testProcess.stdin.write(`${command}\n`)

但我不确定如何正确地做到这一点。看起来我没有将其编码为正确的格式。而且这也不是一个真正的解决方案,我只是手动将表情符号编码为UTF。我可能需要将整个路径转换为UTF-16或其他格式,以确保其中没有不支持的字符:

"E:/test .txt".split("").reduce((hex,c) => hex += c.charCodeAt(0).toString(16).padStart(4,"0"),"")

我不确定它是否能正常工作。

1个回答

4
尝试以下内容:
let childProcess = require('child_process')

let testProcess = childProcess.spawn(
  'chcp 65001 >NUL & powershell.exe -NonInteractive -NoProfile -Command -', 
  { shell: true }
)

testProcess.stdout.on('data', (data) => {
  console.log(data.toString())
})

testProcess.stdout.on('error', (error) => {
  console.log(error)
})

testProcess.stdin.write("Get-Item '.txt'\n");

  • 虽然Node.js 本身默认使用UTF-8编码,但是从它衍生出的控制台应用程序通常会使用系统的活动OEM代码页,例如在美国英语系统上使用代码页437,这通常是一个固定的单字节限制为256个字符,缺乏对大多数Unicode字符的支持。

  • powershell.exe,即Windows PowerShell CLI也不例外,因此为了使其将stdin输入解释为UTF-8,必须在启动powershell.exe之前显式地将OEM代码页设置为UTF-8代码页65001

  • 因此,使用{ shell : true }来确保通过Windows上的默认shell cmd.exe启动powershell.exe,这允许首先执行chcp 65001,以进行切换到UTF-8代码页。

    • 注意:这个切换到UTF-8作为OEM代码页也会影响同一进程中后续对控制台应用程序的调用。
  • 另外:

    • -NonInteractive用于告诉PowerShell会话中不需要用户交互,这特别是防止加载用于命令行编辑的PSReadLine模块,这可能会导致在BMP之外的Unicode字符(即代码点高于0xFFFF的字符,例如)出现问题,这些字符在.NET中需要两个[char]实例。

    • -NoProfile防止加载(点源)PowerShell配置文件,因为它们通常只在交互式会话中需要,并且它们的加载不仅会减慢速度,而且可能会产生副作用

    • -Command -告诉PowerShell从stdin读取命令;虽然省略此参数有些类似,但它相当于-File -,这展示了伪交互式行为


1
你似乎对Shell很熟悉。你喜欢尝试开源项目吗?几天后我将在我的Github页面上发布我的现代高级文件管理器应用程序。如果你愿意,在应用程序发布后,可以查看代码,根据需要进行一些优化。你甚至可能会喜欢使用这个应用程序本身,它为创作者和开发人员提供了许多出色的功能。 - AlekseyHoffman
1
老兄,如约而至,这是应用程序的链接:https://github.com/aleksey-hoffman/sigma-file-manager - AlekseyHoffman
谢谢,@AlekseyHoffman - 看起来非常令人印象深刻。 - mklement0
1
谢谢 :) 今天会推出更新,其中包括一些错误修复和新功能。 - AlekseyHoffman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接