将生成的进程标准输出捕获为 unicode

Jon*_*han 5 c++ unicode winapi stdout io-redirection

在我的 C++/WinAPI 代码中,我想运行一些命令并捕获它们的输出。为了测试非 ASCII 输出,我将网络连接重命名为Eth\xc3\xa9rn\xc3\xa9t \xd7\x90\xd7\x91\xd7\x92 \xd0\x91\xd0\xb1\xd0\x93\xd0\xb3\xd0\x94\xd0\xb4并运行ipconfig. 在命令提示符下运行时,输出正确(使用 Courier New 等支持字体时可见):

\n\n
C:\\>ipconfig\nWindows IP Configuration\n\nEthernet adapter Eth\xc3\xa9rn\xc3\xa9t \xd7\x90\xd7\x91\xd7\x92 \xd0\x91\xd0\xb1\xd0\x93\xd0\xb3\xd0\x94\xd0\xb4:\n(...)\n
Run Code Online (Sandbox Code Playgroud)\n\n

我尝试按照此答案中的示例将输出重定向到管道。但返回的字节数组ReadFile()不是 unicode - 它是用 CP_OEMCP 编码的(在我的例子中是 CP437),因此希伯来语和俄语字符显示为“?”。由于字符已经丢失,任何进一步的处理都无法恢复它们。

\n\n

显然这是可能的,因为控制台窗口中的 cmd 可以做到这一点。我该怎么做?

\n

Har*_*ton 3

ipconfig当它检测到输出设备是控制台时,似乎会产生 Unicode 输出,否则会产生 ANSI 输出。这可能是一种向后兼容性措施。

ipconfig出于同样的原因,大多数其他内置命令行工具可能仅支持 ANSI,或者其行为方式与 ANSI 相同。在 Windows 中,命令行工具意味着在命令行上使用。不鼓励程序员向它们付费并解析输出。相反,您应该使用相应的 API。

如果您知道需要哪种语言,您也许可以选择一个代码页来保留内容。

由@Jonathan 添加:未记录:事实证明您可以使用环境变量控制内置命令的编码OutputEncoding。我使用 ipconfig 进行了测试,但想必它也适用于其他内置工具:

> for %e in ("" Unicode Ansi UTF8) do (set OutputEncoding=%~e& ipconfig >ipconfig-%~e.txt)
> (set OutputEncoding=  & ipconfig  1>ipconfig-.txt )
> (set OutputEncoding=Unicode  & ipconfig  1>ipconfig-Unicode.txt )
> (set OutputEncoding=Ansi  & ipconfig  1>ipconfig-Ansi.txt )
> (set OutputEncoding=UTF8  & ipconfig  1>ipconfig-UTF8.txt )
Run Code Online (Sandbox Code Playgroud)

事实上,ipconfig-*.txt 按预期进行了编码!请注意,这没有记录,但它确实对我有用。

附录:从 Windows 10 v1809 开始,另一种选择是创建伪控制台。