【问题标题】:C++ Getting UTF-8 output from CreateProcess()C++ 从 CreateProcess() 获取 UTF-8 输出
【发布时间】:2026-01-12 05:05:02
【问题描述】:

我无法让它工作,所以我将 UTF-8 输出从 CreateProcess() 获取到 wstring

目前我正在运行此方法,但没有 UTF-8 输出:

HANDLE g_hChildStd_OUT_Rd = NULL;
HANDLE g_hChildStd_OUT_Wr = NULL;
HANDLE g_hChildStd_ERR_Rd = NULL;
HANDLE g_hChildStd_ERR_Wr = NULL;

PROCESS_INFORMATION CreateChildProcess(void);
void ReadFromPipe(PROCESS_INFORMATION);

string run(char *command){
    SECURITY_ATTRIBUTES sa;
    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.bInheritHandle = TRUE;
    sa.lpSecurityDescriptor = NULL;
    if ( ! CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0) ) {
        exit(1);
    }
    if ( ! SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0) ){
        exit(1);
    }
    if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0) ) {
        exit(1);
    }
    if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) ){
        exit(1);
    }
    char *szCmdline=command;
    PROCESS_INFORMATION piProcInfo;
    STARTUPINFO siStartInfo;
    bool bSuccess = FALSE;
    ZeroMemory( &piProcInfo, sizeof(PROCESS_INFORMATION) );
    ZeroMemory( &siStartInfo, sizeof(STARTUPINFO) );
    siStartInfo.cb = sizeof(STARTUPINFO);
    siStartInfo.hStdError = g_hChildStd_ERR_Wr;
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr;
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
    bSuccess = CreateProcess(NULL,
        szCmdline,     // command line
        NULL,          // process security attributes
        NULL,          // primary thread security attributes
        TRUE,          // handles are inherited
        CREATE_NO_WINDOW,             // creation flags
        NULL,          // use parent's environment
        NULL,          // use parent's current directory
        &siStartInfo,  // STARTUPINFO pointer
        &piProcInfo);  // receives PROCESS_INFORMATION
    CloseHandle(g_hChildStd_ERR_Wr);
    CloseHandle(g_hChildStd_OUT_Wr);
    if ( ! bSuccess ) {

        exit(1);
    }
    DWORD dwRead;
    CHAR chBuf[BUFSIZE];
    bool bSuccess2 = FALSE;
    std::string out = "", err = "";
    for (;;) {
        bSuccess2=ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if( ! bSuccess2 || dwRead == 0 ) break;

        std::string s(chBuf, dwRead);
        out += s;
    }
    dwRead = 0;
    for (;;) {
        bSuccess2=ReadFile( g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if( ! bSuccess2 || dwRead == 0 ) break;

        std::string s(chBuf, dwRead);
        err += s;
    }

    return out;
}

我尝试了几件事,但没有成功。

感谢任何帮助!

【问题讨论】:

  • 您为什么希望子进程输出 UTF8 ? Windows 上的 fyi std::wstring 通常用于 UTF16。
  • 当使用 CreateProcess() 执行命令时会打印出一些字符,如 č,ć,ž,所以这就是为什么我需要 wstring。
  • 它们很可能是您需要确定的代码页上的 MBCS。
  • 管道处理原始字节,而不是字符。您遇到问题的输出中的原始字节实际上是什么样的?如果您在此处发布字节以及您期望的字符串输出,那么有人可能会帮助识别正在使用的编码。
  • 我得到了这样的输出:prntscr.com/c7982a,但应该是这样的:prntscr.com/c7989y

标签: c++ winapi utf-8 createprocess


【解决方案1】:

命令的输出是字节流。因此,您将其作为字节流读取。由两个程序就使用的编码达成一致。

例如:


当您随后读取应用程序输出时,您使用约定的编码对字节流进行解码。例如。使用MultiByteToWideChar function

【讨论】:

  • 我认为最后一个项目符号应该参考WriteConsoleA。当你打电话给WriteConsoleW 时,打电话给SetConsolveCP 似乎没什么意义。 WriteFile 部分是正确的;没有 WriteFileA/W 这样的东西,因为它写入二进制数据而不是文本。
  • @MSalters 我不认为你是对的。使用WriteConsoleA,您使用的是OEM编码来指定输出;并使用 WriteConsoleW 您正在使用 UTF-16 LE 编码。并且系统将任一转换为默认编码。但是使用 SetConsoleCP 你可以覆盖任何一个,例如使用UTF-8。您将如何使您的应用程序仅使用 WriteConsoleW 输出 UTF-8?