2017-04-17 52 views
0

我在互聯網上搜索了很多,但他們大多數都在談論reindirect輸出。沒有人給出任何成功的reindirect輸入示例。對於我下面的代碼,當我運行命令「ipconfig」或「192.168.0.10」時,它會給出正確的輸出,因爲在運行這些命令後子進程結束,不需要輸入。但是當我運行命令「ftp」而不是「ipconfig」時,控制檯的子進程正在等待下一個輸入命令。正如你所看到的,我試圖在這種情況下將11111作爲輸入寫入控制檯。然而,控制檯沒有收到我的輸入命令並永遠等待輸入命令。我怎樣才能成功地應對這個計劃「ftp」的命令,並保持控制檯運行我怎樣才能讓createprocess reindirect輸入成功,我已經成功地獲得reindirect輸出結果

#include <windows.h> 
#include <fstream> 
using namespace std; 

int WINAPI WinMain(
        HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR lpComLine, 
        int nCmdShow) 
{ 
    SECURITY_ATTRIBUTES secAttr; 
    HANDLE hRead,hWrite; 

char command[256]; 
char testBuf[256] = {0}; 
    strcpy(command, "ipconfig"); 
// strcpy(command, "ping 192.168.0.10")  
// strcpy(command, "ftp"); 

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

HANDLE hTxtFile = CreateFile("tmp.txt", GENERIC_ALL, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if (hTxtFile == INVALID_HANDLE_VALUE) 
{ 
    MessageBox(NULL, "Error createfile", NULL, MB_OK); 
    return 0; 
} 
HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, 0, &secAttr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 
if (hWriteFile == INVALID_HANDLE_VALUE) 
{ 
    MessageBox(NULL, "Error createWritefile", NULL, MB_OK); 
    return 0; 
} 

STARTUPINFO startupInfo; 
PROCESS_INFORMATION processInfo; 
startupInfo.cb = sizeof(STARTUPINFO); 
GetStartupInfo(&startupInfo); 
startupInfo.hStdError = hTxtFile;  
startupInfo.hStdOutput = hTxtFile; 
startupInfo.hStdInput = hWriteFile; 
startupInfo.wShowWindow = SW_SHOW; 
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; 

char output[10240] = {0}; 
DWORD bytesRead; 

if (!CreateProcess(NULL, command,NULL,NULL,TRUE,NULL,NULL,NULL,&startupInfo,&processInfo)) 
{ 
    MessageBox(NULL, "Error createprocess", NULL, MB_OK); 
    CloseHandle(hWrite); 
    CloseHandle(hRead); 
    return FALSE; 
} 

DWORD processExitCode = 0; 
strcpy(testBuf, "11111\r\n"); 
while (GetExitCodeProcess(processInfo.hProcess, &processExitCode)) 
{ 
    WriteFile(hWriteFile, testBuf, 7, &bytesRead, NULL); 
    if (processExitCode != STILL_ACTIVE) 
    { 
     // MessageBox(NULL, "End process", NULL, MB_OK); 
     break; 
    } 
    Sleep(1000); 
} 

SetFilePointer(hTxtFile, NULL, NULL, FILE_BEGIN); 
ReadFile(hTxtFile, output, 10240, &bytesRead, NULL); 
CloseHandle(hTxtFile); 

MessageBox(NULL, output, NULL, MB_OK); 

return 0; 
} 
+0

1)需要關閉句柄,你不做2)'hStdInput'必須有'FILE_GENERIC_READ'訪問3)大多數程序時查看空輸入('NumberOfBytesRead == 0'或* ZwReadFile *回報* STATUS_END_OF_FILE *)只需退出 - 所以你的代碼將不會與文件系統文件一起工作。或者在創建進程之前需要將數據寫入'hStdInput' *。 – RbMm

+0

4)一般說明 - 在使用同步共享文件時使用它 - 不正確 - 文件共享* CurrentByteOffset *。當你調用* WriteFile *時,你可以不從你認爲的位置寫入,因爲子進程可以改變位置(這可以避免在* OVERLAPPED *中使用直接偏移)。你的寫改變* CurrentByteOffset *在共享文件對象,並影響子進程5)使用'processExitCode!= STILL_ACTIVE'不是100%可靠的方式 - 如果子調用ExitProcess(STILL_ACTIVE)'? – RbMm

+0

我已經在我的項目中找到了問題,所以基本上在我們使用STARTF_USESTDHANDLES屬性時。 createprocess將創建非交互式控制檯,這意味着它只能在createprocess調用中運行一個命令行。任何想法我可以使用createprocess創建一個交互式重定向控制檯,它根據最後的控制檯輸出接受用戶輸入?非常感謝 –

回答

2

重定向(不是「reindirecting」)輸入的工作方式一樣重定向輸出。當然,數據的流向是相反的。這意味着從文件讀取的過程爲。這也就意味着,當你打開一個手柄以寫入,就像您在示例代碼做:

HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_WRITE, ...); 

進程將無法從中讀取。您必須打開文件進行讀取:

HANDLE hWriteFile = CreateFile("Write.txt", GENERIC_READ, ...); 

不過,這也意味着你必須準備要下來發送給該進程提前輸入。在創建過程之後,寫入文件無濟於事。

如果您不知道必須提前發送到進程的數據,則不能使用文件進行標準輸入,但必須使用其他內容,例如(命名或匿名)管道。

0

必須重定向控制檯輸出,然後寫入緩衝區中的文件

1)

/* Create a pipe for the child process's STDOUT */ 
    if(!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) 
     BAIL_OUT(-1); 

2)

/* Duplicate the pipe HANDLE */ 
    if (!DuplicateHandle(GetCurrentProcess(), hChildStdoutRd, GetCurrentProcess(), &hChildStdoutRdDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) 
     BAIL_OUT(-1); 

3)

CHAR chBuf[BUFSIZE]; 
    DWORD dwRead; 
    DWORD dwAvail = 0; 
    if (!PeekNamedPipe(hChildStdoutRdDup, NULL, 0, NULL, &dwAvail, NULL) || !dwAvail) 
     return; 
    if (!ReadFile(hChildStdoutRdDup, chBuf, min(BUFSIZE - 1, dwAvail), &dwRead, NULL) || !dwRead) 
     return; 
    chBuf[dwRead] = 0; 

請找更多細節在這裏: https://www.codeproject.com/Articles/5531/Redirecting-an-arbitrary-Console-s-Input-Output

+0

http://stackoverflow.com/questions/26398214/redirect-ftp -pipe-in​​-c在這裏,我改變了我的代碼,現在它完美的工作,但是我遇到了與此OP相同的問題。當我們在真實控制檯輸入「ftp」或「wmic」時,我們會收到「ftp>」,當我們輸入一個無效的命令如「123」時,我們會收到「無效命令」。但是,父進程和子控制檯進程之間的這種交互操作不會發生在我的代碼或我在互聯網上找到的所有重定向程序中。我已經下載了這個演示,並且在運行它時也遇到了同樣的問題 –

相關問題