2013-10-29 35 views
5

我使用CreateProcess來啓動一個交互式腳本解釋器,並希望透明地將stdin/stdout/stderr從/傳遞給解釋器。如何正確啓動進程並轉發stdin/stdout/stderr?

我第一次嘗試以設置STARTUPINFO結構傳遞到CreateProcess

STARTUPINFOA si = { sizeof(si) }; 
si.hStdError = ::GetStdHandle(STD_ERROR_HANDLE); 
si.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE); 
si.hStdInput = ::GetStdHandle(STD_INPUT_HANDLE); 
si.dwFlags |= STARTF_USESTDHANDLES; 

即我試圖讓腳本解釋器進程使用與我的啓動器進程使用的相同的句柄來讀/寫。這似乎並沒有工作,雖然(我甚至不知道這些標準句柄可以繼承)。

基於Creating a Child Process with Redirected Input and Output示例的第二個想法是設置三個管道來轉發寫入任何管道的所有數據。由於我不知道如何等待數據寫入多個文件(WaitForMultipleObjects無法在管道上同步),因此我正在考慮設置三個線程,每個線程都會在管道上執行阻塞ReadFile調用。

我懷疑這可能是矯枉過正,所以我想知道:有沒有更簡單的方法來做到這一點?我不需要對從腳本解釋器傳遞過來的數據進行任何類型的處理。

作爲一個方面說明,在Linux上,我使用execvp只是用腳本解釋器進程替換當前進程,但在Windows上,我需要啓動腳本解釋器,使主線程處於掛起狀態(以便我可以做一些字節碼修補) - 即使因爲_execvp似乎在Windows上可用,我必須使用CreateProcess。

+2

[Create CreateProcess inherited the calling of the calling process](http://stackoverflow.com/questions/340356/making-createprocess-inherit-the-console-of-the-calling-process) –

+2

Re :如何在多個文件上等待I/O。您爲每個文件句柄創建一個'OVERLAPPED'結構,並帶有一個事件句柄,併發出異步I/O請求(例如'ReadFile'),以傳遞這些'OVERLAPPED'結構。然後等待這些事件句柄。 –

+0

你能否在一個答案中詳細說明@Igor?這似乎是從[以前]的主要區別(http://stackoverflow.com/questions/5485923/launch-an-exe-process-with-stdin-stdout-and-stderr)[問題](http://堆棧溢出。com/questions/340356/making-createprocess-inherit-the-console-of-calling-process)。 – Shog9

回答

1

如圖中的OP Popuplating的STARTUPINFO如果您確保未通過CREATE_NO_WINDOW論點的CreateProcessdwFlags參數正常工作。

4

爲了在多個文件或管道上等待I/O,可以在每個文件上發出異步I/O請求,然後等待所有請求的完成。沿着這些線路(未經測試)的東西:

HANDLE file1, file2; // initialized somehow 

HANDLE events[2]; 
events[0] = CreateEvent(NULL, TRUE, FALSE, NULL); 
events[1] = CreateEvent(NULL, TRUE, FALSE, NULL); 

OVERLAPPED overlapped1 = {0}; 
overlapped1.hEvent = events[0]; 
OVERLAPPED overlapped2 = {0}; 
overlapped2.hEvent = events[1]; 

ReadFile(file1, buffer1, size1, NULL, &overlapped1); 
ReadFile(file2, buffer2, size2, NULL, &overlapped2); 

WaitForMultipleObjects(2, events, FALSE, INFINITE); 

ReadFileWaitForMultipleObjects需要在一個循環中調用。您檢查返回值WaitForMultipleObjects以知道哪個操作已完成,請使用GetOverlappedResult來發現該操作的結果(是否成功,如果是,它檢索了多少個字節),處理數據,如果該句柄再次調用ReadFile if你想從中讀更多,然後回到等待。這有點類似於Linux中由select驅動的非阻塞I/O循環。

更先進的技術是I/O completion ports。這可以讓一個線程池處理大量的異步I/O。通常用於Web服務器等,可能是你的情況矯枉過正。

+0

+1這看起來非常好! –