void __fastcall BuildAndMessage(AnsiString PathToBuild/*=NULL*/, AnsiString Set/*=NULL*/)
{
AnsiString CommandStr = MakeCommandStr(PathToBuild, Set);
//ShowMessage(CommandStr);
// 讀管道
HANDLE hChildStdinWr/*父進程寫*/, hChildStdinRd/*子進程讀*/;
// 寫管道
HANDLE hChildStdoutWr/*子進程寫*/, hChildStdoutRd/*父進程讀*/;
SECURITY_ATTRIBUTES sa;
_di_IOTAMessageServices MessageServices;
_di_IOTAMessageGroup MessageGroup;
if (BorlandIDEServices->Supports(MessageServices))
{
MessageServices->ClearToolMessages(NULL);
MessageGroup = MessageServices->AddMessageGroup("Ddkbuild");
MessageServices->ShowMessageView(MessageGroup);
}
else
{
ShowMessage("Create ddkbuild messageview failed");
return;
}
sa.bInheritHandle = true;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
// 創建子進程寫管道
if (!CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &sa, 0))
{
ShowMessage("Create Stdout pipe failed");
return;
}
SetHandleInformation(hChildStdoutRd, HANDLE_FLAG_INHERIT, 0); // 該句柄子進程沒用到,故取消繼承性
// 創建子進程讀管道
if (!CreatePipe(&hChildStdinRd, &hChildStdinWr, &sa,0))
{
ShowMessage("Create StdinRd pipe failed");
return;
}
SetHandleInformation(hChildStdinWr, HANDLE_FLAG_INHERIT, 0); // 該句柄子進程沒用到,故取消繼承性
//SetStdHandle(STD_OUTPUT_HANDLE, hChildStdoutWr);
//SetStdHandle(STD_INPUT_HANDLE, hChildStdinRd);
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(STARTUPINFO);
si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
si.hStdInput = hChildStdinRd; // 重定向子進程輸入
si.hStdOutput = hChildStdoutWr; // 重定向子進程輸出
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
// 註意使用了true,這樣創建子進程時,父進程的所有可繼承的句柄就可以被繼承下來了
// 我們也可以使用SetHandleInformation使句柄不可被繼承,這樣子進程就無法使用了
// 這樣的例子可以看《Creating a Child Process with Redirected Input and Output.doc》
if (!CreateProcess(NULL, CommandStr.c_str(), NULL, NULL, true, 0, NULL, NULL, &si, &pi))
{
ShowMessage("Create process failed");
return;
}
// 將數據寫入子進程,這裏只是演示,本程序不需要寫入
const char *strIn = " ";
DWORD dwBytes = 0;
WriteFile(hChildStdinWr, strIn, strlen(strIn), &dwBytes, NULL);
CloseHandle(hChildStdinWr); // 保證對端的ReadFile可返回
// 調用ReadFile前須關閉,否則因寫管道寫入端有未關閉的Write句柄,ReadFile最後無法返回0
CloseHandle(hChildStdoutWr);
// 從子進程中讀出執行結果,不處理mbcs,需要的朋友請加上前導字符的判斷
char strData[MAX_PATH * 2];
AnsiString MessageComplete, MessageCut;
char* pos;
char lf = '\n';
void* Unused = 0;
while (ReadFile(hChildStdoutRd, strData, sizeof(strData), &dwBytes, NULL))
{
strData[dwBytes] = 0;
if (pos = strrchr(strData, lf)) // 如果有換行,則顯示
{
*(pos-1) = 0;
pos++;
MessageComplete = MessageCut + strData;
MessageCut = pos;
MessageServices->AddToolMessage(
"", MessageComplete, "Ddkbuild", 0, 0, NULL, Unused, MessageGroup);
}
else // 否則暫存
MessageCut = MessageCut + strData;
Application->ProcessMessages();
}
MessageServices->AddToolMessage(
"", MessageCut, "Ddkbuild", 0, 0, NULL, Unused, MessageGroup);
// 關閉句柄
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(hChildStdinRd);
CloseHandle(hChildStdoutRd);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}