2015-10-14 147 views
-1

我試圖打印cmd命令的輸出和輸入接收到標準輸出,就像一個正常的cmd.exe會做的那樣。 我可以使用函數_popen,但是當我啓動Python或Powershell這樣的程序時,它不起作用。 所以我需要輸出的子進程,並能夠發送命令到子進程。通過管道重定向CMD.exe輸出和c輸入

有一個simmilar問題here

所以我修改了代碼從this鏈接看起來像這樣:

void WriteToPipe(char* command){ 
    DWORD dwRead, dwWritten; 
    BOOL bSuccess = FALSE; 

    bSuccess = WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL); 

    // Close the pipe handle so the child process stops reading. 

    if (!CloseHandle(g_hChildStd_IN_Wr)) 
     ErrorExit(TEXT("StdInWr CloseHandle")); 
} 

void ReadFromPipe(void){ 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE; 
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

    bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); 
    bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL); 
    //bSuccess = PeekNamedPipe(g_hChildStd_OUT_Rd, NULL, BUFSIZE, &dwRead, &dwTotalAvailBytes, &dwBytesLeft); 
} 

主循環看起來是這樣的:

CreateChildProcess("C:\\Python27\\python.exe"); 
char input_buffer[100] = { 0 }; 
while (1){ 
    fgets(input_buffer, 99, stdin); 
    WriteToPipe(input_buffer); 
    ReadFromPipe(); 
} 

一切其他(從代碼)保持不變。

現在我的問題是,我想輸入多個命令到同一個進程,但是在WriteToPipe中有一個CloseHandle函數,在句柄關閉後我不能輸入更多的命令。

如何獲得一個有效的句柄來寫入超過1個命令的過程?

+0

在函數中:'ReadFromPipe'局部變量'bSuccess'設置在每個子函數調用中,但從不使用。你的編譯器應該告訴你這個問題。編譯時,始終啓用所有警告,然後修復警告。 (對於gcc,至少使用:'-Wall -Wextra -pedantic') – user3629249

+0

由於您使用的是windows函數,而不是使用函數CreateChildProcess(),所以使用Windows的CreateProcess,那麼您可以替換stdin,stdout和stderr HANDELS。你會得到更多的控制權。有很多教程關於那 – milevyo

+0

@ user3629249我知道,但它像我說的第一個2調用工作.... – test123423

回答

-2

將ReadFromPipe()放在單獨的線程中; 我的代碼在這裏是垃圾,但它是工作代碼,它僅用於測試目的。

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

#define BUFSIZE 4096 

HANDLE g_hChildStd_IN_Rd = NULL; 
HANDLE g_hChildStd_IN_Wr = NULL; 
HANDLE g_hChildStd_OUT_Rd = NULL; 
HANDLE g_hChildStd_OUT_Wr = NULL; 

HANDLE g_hInputFile = NULL; 

int CreateChildProcess(TCHAR *szCmdline); 

void PrintError(char *text,int err); 
int InitPipes(); 


int WriteToPipe(char* command){ 
    DWORD dwRead, dwWritten; 
    BOOL bSuccess = FALSE; 
    SetLastError(0); 
    WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL); 


    bSuccess=GetLastError(); 

    PrintError("WriteToPipe",bSuccess); 
    return (bSuccess==0)||(bSuccess==ERROR_IO_PENDING); 
} 

int ReadFromPipe(void){ 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE; 
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

    SetLastError(0); 
    while(
     ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL) 
     && 
     WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL) 
     ); 

    bSuccess=GetLastError(); 
    PrintError("ReadFromPipe",bSuccess); 


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

HANDLE hThread; 

int __stdcall ThreadProc(int arg){ 

    while(ReadFromPipe()) 
     ; 

    return 0; 
} 

int main(){ 
    char input_buffer[100] = { 0 }; 
    if(!InitPipes()){ 
     printf("Failed to CreatePipes\n"); 
     return -1; 
    } 

    if(!CreateChildProcess("cmd.exe")){ 
     printf("Failed to create child process\n"); 
     return -2; 
    } 


    hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL); 

    while (1){ 
     fgets(input_buffer, 99, stdin); 
     if(!WriteToPipe(input_buffer)) break; 
    } 
    printf("Program terminated\n"); 
    return 0; 
} 





int CreateChildProcess(TCHAR *szCmdline){ 

    PROCESS_INFORMATION piProcInfo; 
    STARTUPINFO siStartInfo; 
    BOOL bSuccess = FALSE; 

// Set up members of the PROCESS_INFORMATION structure. 

    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); 

// Set up members of the STARTUPINFO structure. 
// This structure specifies the STDIN and STDOUT handles for redirection. 

    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); 
    siStartInfo.cb = sizeof(STARTUPINFO); 
    siStartInfo.hStdError = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdInput = g_hChildStd_IN_Rd; 
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES; 

// Create the child process. 

    bSuccess = CreateProcess(NULL, 
     szCmdline,  // command line 
     NULL,   // process security attributes 
     NULL,   // primary thread security attributes 
     TRUE,   // handles are inherited 
     0,    // creation flags 
     NULL,   // use parent's environment 
     NULL,   // use parent's current directory 
     &siStartInfo, // STARTUPINFO pointer 
     &piProcInfo); // receives PROCESS_INFORMATION 

    // If an error occurs, exit the application. 
    if ( bSuccess){ 
     // Close handles to the child process and its primary thread. 
     // Some applications might keep these handles to monitor the status 
     // of the child process, for example. 

     CloseHandle(piProcInfo.hProcess); 
     CloseHandle(piProcInfo.hThread); 
    } 
    return bSuccess; 
} 



int InitPipes(){ 
    SECURITY_ATTRIBUTES saAttr; 

// Set the bInheritHandle flag so pipe handles are inherited. 

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 



    if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) 
     return 0; 

    if (! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) 
     return 0; 

    if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
     return 0; 

    if (! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) 
     return 0; 

    return 1; 
} 





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 ; 

} 
+0

注意輸入的udplicate輸出,嘗試修復它; – milevyo

+0

thx即時測試現在 – test123423

+0

測試結果是什麼? – milevyo

-1
int WriteToPipe(char* command){ 
    DWORD dwRead, dwWritten; 
    BOOL bSuccess = FALSE; 

    bSuccess = WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL); 

    return bSuccess ; 
} 

關閉main()函數的句柄,因爲g_hChildStd_IN_Wr是全球性的。 return bSuccess;如果寫入管道已成功,則通知您

+0

與ReadFromPipe使用相同的東西,檢查主函數中的成功 – milevyo

+0

我也嘗試過,但在第二個命令後掛起 – test123423