2017-01-18 9 views
0

私はこの日にこだわっています。私はgoind crazyです。 基本的には、私はスレッドでcmd.exeを開き、それに親からの入力と読み取り出力を与えようとしています。同様に、Linuxにttyを割り当てるのと同じように、ウィンドウにそのようなことはありません。私はLinuxシステムについてよく理解していますが、Windowsについても同じことは言えません。CreateProcess()スレッドからパイプを読み取ることができません

ので、ここでは、「私」のコードです:

#undef UNICODE 


    #include <windows.h> 
    #include <tchar.h> 
    #include <stdio.h> 
    #include <strsafe.h> 


    //using namespace std; 
    #define BUFFER_SIZE 99 

    // handles for cmd thread pipes 
    HANDLE cmd_in_rd = NULL; 
    HANDLE cmd_in_wr = NULL; 
    HANDLE cmd_out_rd = NULL; 
    HANDLE cmd_out_wr = NULL; 

    HANDLE cmd_thread_handle; 


    void PrintError(char *text, int err) { 
    DWORD retSize; 
    LPTSTR pTemp = NULL; 

    if (!err) return; 

    retSize = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_ARGUMENT_ARRAY, 
     NULL, 
     err, 
     LANG_NEUTRAL, 
     (LPTSTR)&pTemp, 
     0, 
     NULL); 


    if (pTemp) printf("%s: %s\n", text, pTemp); 
    LocalFree((HLOCAL)pTemp); 
    return; 

    } 


    int pipewrite(char *command) { 
    DWORD dwRead, dwWritten; 
    BOOL bSuccess = FALSE; 
    SetLastError(0); 
    WriteFile(cmd_in_wr, command, strlen(command), &dwWritten, NULL); 
    bSuccess = GetLastError(); 
    PrintError("WriteToPipe", bSuccess); 
    return (bSuccess == 0) || (bSuccess == ERROR_IO_PENDING); 
    } 

    int __stdcall cmd_thread(int arg) { 
    // this function only prints when data is ready 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFFER_SIZE]; 
    BOOL bSuccess = FALSE; 
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

    int rf_ret, wf_ret; 

    //CloseHandle(cmd_out_wr); makes readfile fail!! 

    SetLastError(0); 
    while (1) { // only executes once!!!!!!! 
     (rf_ret = ReadFile(cmd_out_rd, chBuf, BUFFER_SIZE, &dwRead, NULL)) 
      && 
      (wf_ret = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL)); 
     printf("ReadFile returned: %d\nWriteFile returned: %d\n", rf_ret, wf_ret); 
     bSuccess = GetLastError(); 
     PrintError("ReadingFromPipe", bSuccess); 
    } 

    bSuccess = GetLastError(); 
    return (bSuccess == 0) || (bSuccess == ERROR_IO_PENDING); 
    } 


    int main(void) { 

    char buffer[BUFFER_SIZE]; 

    // init the pipes 
    SECURITY_ATTRIBUTES cmd_sa; 
    cmd_sa.nLength = sizeof(SECURITY_ATTRIBUTES); 
    cmd_sa.bInheritHandle = TRUE; 
    cmd_sa.lpSecurityDescriptor = NULL; 

    if (!CreatePipe(&cmd_out_rd, &cmd_out_wr, &cmd_sa, 0)) { 
     printf("%s\n", "Error creating pipes"); 
     return 1; 
    } 

    if (!SetHandleInformation(cmd_out_rd, HANDLE_FLAG_INHERIT, 0)) { 
     printf("%s\n", "Error setting handle infos"); 
     return 1; 
    } 

    if (!CreatePipe(&cmd_in_rd, &cmd_in_wr, &cmd_sa, 0)) { 
     printf("%s\n", "Error creating pipes"); 
     return 1; 
    } 

    if (!SetHandleInformation(cmd_in_rd, HANDLE_FLAG_INHERIT, 0)) { 
     printf("%s\n", "Error setting handle infos"); 
     return 1; 
    } 

    // create the cmd thread 
    PROCESS_INFORMATION cmd_pi; 
    STARTUPINFO cmd_si; 
    ZeroMemory(&cmd_pi, sizeof(PROCESS_INFORMATION)); 
    ZeroMemory(&cmd_si, sizeof(STARTUPINFO)); 
    cmd_si.cb = sizeof(STARTUPINFO); 
    cmd_si.hStdError = cmd_out_wr; 
    cmd_si.hStdOutput = cmd_out_wr; 
    cmd_si.hStdInput = cmd_in_rd; 
    cmd_si.dwFlags |= STARTF_USESTDHANDLES; 

    TCHAR comm[] = TEXT("cmd.exe"); 
    BOOL th = CreateProcess(NULL, 
     comm, 
     NULL, 
     NULL, 
     TRUE, // handles are inherited 
     0, 
     NULL, 
     NULL, 
     &cmd_si, 
     &cmd_pi); 

    if (th) { 
     CloseHandle(cmd_pi.hProcess); 
     CloseHandle(cmd_pi.hThread); 
    } 

    cmd_thread_handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)cmd_thread, NULL, 0, NULL); 

    // read commands from shell and send them to cmd 
    ZeroMemory(&buffer, BUFFER_SIZE); 
    while (1) { 
     fgets(buffer, BUFFER_SIZE, stdin); 
     if (!pipewrite(buffer)) break; 
    } 
    printf("Program terminated\n"); 

    return 0; 
    } 

私は実際には、テスト目的のために、私はそれが私のメインプログラムで動作させることができなかったので、stackoverflowの上およびMSDNから別の質問から多くのことをコピーしたが。私が理解していないことは次のとおりです:

なぜcmd_threadの中のwhileループが起動時に実行され、そこでハングして世界の終わりを待っていますか?私は読み取りの前に親からパイプout_writeハンドルを閉じようとしましたが、それは他の部分が動作しないようにします。

pipewrite()は動作しているようですが、cmd.exeスレッドが入力を受け取り、動作していることを確認できません...出力が得られないので:/ プログラムの実行中または実行中それはデバッガには、しかし、私はそのためのツールを知っていません... 奇妙なことは、original作品(私はどこにコードを持っている)です。私はその2つの違いを見つけようとしましたが、私はそれらを並べて見ても、まったく同じことをするようです。これはされている必要があります

if (!SetHandleInformation(cmd_in_rd, HANDLE_FLAG_INHERIT, 0)) { 

if (!SetHandleInformation(cmd_in_wr, HANDLE_FLAG_INHERIT, 0)) { 

元のコードのようにので

+0

なぜGetLastErrorの戻り値をBOOLに入れていますか? –

+0

[リダイレクトされた入力と出力を持つ子プロセスを作成する](https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499.aspx) –

答えて

0

子プロセスは、できるだけ早くそれが標準入力から読み取ろうとして死にかけています。

また、エラー処理はほとんど間違っています。一貫してエラーをチェックするのではなく、エラーが発生していないときにGetLastError()を呼び出すことがあります。 (これらの問題も元のコードにあります)

に電話をかける必要があります。そうしないと、子がいつ終了するかを知ることができなくなるからです。

偶然にも、cmd.exeは、のプロセスであり、スレッドではありません。

+0

ありがとうございました!私はそれを見ていないとは信じられない...!私はエラー処理が混乱していることを知っている、すべてのコードが混乱している、私はちょうどうまくいく仕事を得るためにそれを修正していた、これはahah –

関連する問題