2016-08-17 4 views
2

私はUTF-8出力をCreateProcess()からwstringに取得することができません。C++ CreateProcess()からUTF-8出力を取得する

は現在、私はそれを行うには、この方法を実行していますが、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; 
} 

私はいくつかのことを試してみましたが、作業それを作ることに成功しませんでした。

ご協力いただきましてありがとうございます。

+1

なぜ、子プロセスがUTF8を出力すると思われますか? Windowsのfyi std :: wstringは、通常、UTF16に使用されます。 –

+0

CreateProcess()を使ってコマンドを実行したときに表示されるč、ć、¼などの文字があるので、wstringでそれを必要としています。 – MrWhite

+1

これらは、決定する必要があるコードページのMBCSの可能性が最も高いです。 –

答えて

3

コマンドの出力はバイトストリームです。だからあなたはバイトストリームとしてそれを読む。使用するエンコーディングに同意するのは2つのプログラムに任されています。例えば

  • は、.NET(C#/ VB.NET)コンソールアプリケーションを実行すると、アプリケーションはConsole.Write[Line] methodが使用するエンコーディングを設定するために、Console.OutputEncodingを使用することができます。

    Console.OutputEncoding = Text.Encoding.UTF8; 
    
  • 同様に、PowerShellスクリプトは、Write-Output又はWrite-Hostコマンドレットが使用するエンコーディングを設定するために、[Console]::OutputEncodingを使用することができます。

    [Console]::OutputEncoding = [Text.Encoding]::UTF8 
    
  • cmd.exeまたはバッチファイルchcp commandを使用することができます。

    chcp 65001 
    
  • A Win32アプリケーションは、それがWriteConsoleを使用している場合SetConsoleOutputCP functionには、その出力エンコーディングを設定し使用することができます。アプリケーションがWriteFileを使用している場合は、既に希望のとおりにエンコードされたバイトを書き込むだけで済みます(例えば、WideCharToMultiByteを使用)。

    SetConsoleOutputCP(CP_UTF8); 
    

あなたは、アプリケーションの出力を読んだとき、あなたは、合意されたエンコーディングを使用して、バイトストリームをデコードします。例えば。 MultiByteToWideChar functionを使用してください。

+0

私は最後の箇条書きは 'WriteConsoleA'を参照するべきだと思います。 'WriteConsoleW'を呼び出すときに、' SetConsolveCP'を呼び出すのは少し難しそうです。 'WriteFile'部分は正しいです。 'WriteFileA/W'はテキストの代わりにバイナリデータを書き込むため、このようなことはありません。 – MSalters

+1

@MSalters私はあなたが正しいとは思わない。 'WriteConsoleA'を使用する場合は、OEMエンコーディングを使用して出力を指定しています。あなたがUTF-16 LEエンコーディングを使用している 'WriteConsoleW'を使用しています。そして、システムはいずれかをデフォルトのエンコーディングに変換します。しかし、 'SetConsoleCP'を使うと、どちらかをオーバーライドして、 UTF-8。'WriteConsoleW'だけであなたのアプリケーションがUTF-8をどのように出力するのですか? –

関連する問題