【发布时间】:2021-08-30 18:22:44
【问题描述】:
我无法将正确的 utf-8 字符串写入 powershell 子进程。 ASCII 字符有效,但 utf-8 字符,例如'ü',会有不同的解释。从同一个 powershell 子进程读取时出现同样的问题。
总结:我想通过我的程序使用 utf-8 编码的 powershell。
更新:
使用AllocConsole(); 分配控制台,然后调用SetConsoleCP(CP_UTF8); 和SetConsoleOutputCP(CP_UTF8);,正如@mklement 在他的回答中提到的那样,如果您有一个没有任何控制台的GUI 应用程序,它对我有用。如果您有控制台应用程序,则不必手动分配控制台。
更新 2:
如果你有一个 GUI 并调用了AllocConsole(),你可以在之后调用ShowWindow(GetConsoleWindow(), SW_HIDE); 来隐藏控制台,如here 所述。
到目前为止我所尝试的:
- 将输入和输出编码设置为 utf-8
$OutputEncoding = [System.Console]::OutputEncoding = [System.Console]::InputEncoding = [System.Text.Encoding]::UTF8进程内 - 对 UTF-16 执行相同操作以防出现错误,例如
...ext.Encoding]::Unicode - 对 ISO-Latin 1 (cp1252) 执行相同操作
- 使用 wchar_t 作为所有测试编码的缓冲区和输入
- 测试给定字符串的字节顺序
- 测试 Unicode(每个字符 4 个字节,而不是 2 个)
- 自己一点一点的构建字符串
- 将编译器标志设置为 \D UNICODE
编写代码示例:
std::string test("ls ä\n");
DWORD ret = WriteFile(std_in_write, test.c_str(), test.size(), &number_of_bytes_written, nullptr);
if (ret == 0) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_WRITE_TO_FILE, GetLastError());
}
输出:ls ├ñ
示例代码:
HANDLE std_in_read = nullptr;
HANDLE std_in_write = nullptr;
HANDLE std_out_read = nullptr;
HANDLE std_out_write = nullptr;
SECURITY_ATTRIBUTES security_attr;
STARTUPINFO startup_info;
PROCESS_INFORMATION process_information;
DWORD buffer_size = 1000000;
security_attr = {sizeof(SECURITY_ATTRIBUTES), nullptr, true};
if (!CreatePipe(&std_in_read, &std_in_write, &security_attr, buffer_size)) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_CREATE_IN_PIPE, GetLastError());
}
if (!CreatePipe(&std_out_read, &std_out_write, &security_attr, buffer_size)) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_CREATE_OUT_PIPE, GetLastError());
}
GetStartupInfo(&startup_info);
startup_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
startup_info.wShowWindow = SW_HIDE;
startup_info.hStdOutput = std_out_write;
startup_info.hStdError = std_out_write;
startup_info.hStdInput = std_in_read;
if (!CreateProcess(TEXT(default_powershell_path), nullptr, nullptr, nullptr, TRUE, 0, nullptr, TEXT(default_windows_path), &startup_info, &process_information)) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_CREATE_PROCESS, GetLastError());
}
std::string test("ls ä\n");
DWORD ret = WriteFile(std_in_write, test.c_str(), test.size(), &number_of_bytes_written, nullptr);
if (ret == 0) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_WRITE_TO_FILE, GetLastError());
}
DWORD dword_read;
while (true) {
DWORD total_bytes_available;
if (PeekNamedPipe(std_out_read, nullptr, 0, nullptr, &total_bytes_available, nullptr) == 0) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_COPY_FROM_PIPE, GetLastError());
}
if (total_bytes_available != 0) {
DWORD minimum = min(buffer_size, total_bytes_available);
char buf[buffer_size];
if (ReadFile(std_out_read, buf, minimum, &dword_read, nullptr) == 0) {
throw PowershellHelper::Exception(PowershellHelper::Exception::Error::COULD_NOT_READ_FILE, GetLastError());
}
std::string tmp(buf);
std::cout << tmp << std::endl;
}
if (total_bytes_available == 0) {
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
注意:redirect-input-and-output-of-powershell-exe-to-pipes-in-c 不能重复,因为该代码仅适用于 ASCII 字符,根本无法处理 utf-8 字符。
也没有 c-getting-utf-8-output-from-createprocess 的重复项,因为建议的解决方案不会像上面提到的那样起作用,我想输入 utf-8 以及读取 utf-8。
【问题讨论】:
标签: c++ windows powershell utf-8 pipe