標籤:readfile createpipe 子進程 輸出 windows
情境:
1. 有一些外部工具命令需要通過程式調用,比如啟動伺服器或者使用網路命令擷取輸出。
2. 使用了匿名管道CreatePipe擷取子進程輸出.
參考:
1. MSDN的主題《Creating a Child Process with Redirected Input and Output》。
2. 《Windows核心編程》進程章節.
代碼:
#include "test_shellrun.h"#include <stdlib.h>#include <stdint.h>#include <iostream>#include <Windows.h>using namespace std;bool ExecuteCommandNoWait(const wchar_t* command){STARTUPINFOW startupInfo = {sizeof(STARTUPINFOW)};GetStartupInfoW(&startupInfo);startupInfo.dwFlags=0;startupInfo.wShowWindow=SW_HIDE;bool ret = true;PROCESS_INFORMATION info;wchar_t* wlpcmd = wcsdup(command);if (CreateProcessW(NULL , wlpcmd , NULL , NULL , TRUE , CREATE_NO_WINDOW, NULL, NULL, &startupInfo, &info)){CloseHandle(info.hProcess);CloseHandle(info.hThread);}else{ ret = false; }free(wlpcmd);return ret;}std::string ExecuteCommandAndWait(const wchar_t* command,uint32_t wait_millisecond){SECURITY_ATTRIBUTES sa;HANDLE hChildStdoutRd,hChildStdoutWr;sa.nLength = sizeof(SECURITY_ATTRIBUTES);sa.lpSecurityDescriptor = NULL;sa.bInheritHandle = TRUE;std::string buf;if (!CreatePipe(&hChildStdoutRd,&hChildStdoutWr,&sa,0)){return buf;}if (!SetHandleInformation(hChildStdoutRd, HANDLE_FLAG_INHERIT, 0)){CloseHandle(hChildStdoutWr);CloseHandle(hChildStdoutRd);return buf;}STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory( &pi, sizeof(PROCESS_INFORMATION) );ZeroMemory( &si, sizeof(STARTUPINFO) );si.cb = sizeof(STARTUPINFO); si.hStdError = hChildStdoutWr;si.hStdOutput = hChildStdoutWr;si.dwFlags |= STARTF_USESTDHANDLES;wchar_t* wlpcmd = wcsdup(command);//CREATE_UNICODE_ENVIRONMENTif (!CreateProcessW(NULL, wlpcmd,NULL,NULL,TRUE,0 ,NULL,NULL,&si,&pi)){ CloseHandle(hChildStdoutWr);CloseHandle(hChildStdoutRd);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);free(wlpcmd);return buf;}WaitForSingleObject(pi.hProcess,wait_millisecond);CloseHandle(pi.hProcess);CloseHandle(pi.hThread);CloseHandle(hChildStdoutWr);char buffer[1024] = {0};DWORD bytesRead;BOOL ret = false;while (true){ret = ReadFile(hChildStdoutRd,buffer,1024,&bytesRead,NULL);if (!ret || bytesRead == 0){break;}buf.append(buffer,bytesRead);}CloseHandle(hChildStdoutRd);free(wlpcmd);return buf;}
調用:
ExecuteCommandNoWait(L"notepad.exe");std::string output = ExecuteCommandAndWait(L"ping www.baidu.com",-1);cout << "output: " << output << endl;
注意:ReadFile在讀取孫子進程的輸出時,就是子進程又建立了子進程,會卡住,這個問題暫時用一個線程定時器調用:
CancelIoEx
關閉ReadFile,目前沒有更好的辦法,有誰知道的留了言.
[Windows]_[初級]_[建立獨立子進程和讀取子進程的輸出]