创建新的进程并等待返回结果
创建新的进程并等待返回结果
创建新的普通进程并等待返回结果
说明:创建新的进程,等待进程返回执行结果
DWORD RunCommandProcessor(const PTCHAR pszCmd)
{
ASSERT(NULL != pszCmd);
STARTUPINFO si = {sizeof(STARTUPINFO)};
si.dwFlags = STARTF_USESHOWWINDOW;
PROCESS_INFORMATION pi = {0};
CString strCurDir;
(void)GetModuleFileName(NULL, strCurDir.GetBuffer(MAX_PATH), MAX_PATH - 1);
strCurDir.ReleaseBuffer();
strCurDir = strCurDir.Left(strCurDir.ReverseFind(_T('\\')));
CString strCmdLine;
strCmdLine.Format(_T("%s\\%s"), strCurDir, pszCmd);
BOOL bRet = CreateProcess(NULL, (LPTSTR)(LPCTSTR)strCmdLine,
NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
DWORD dwExitCode = 0;
if (bRet)
{
(void)CloseHandle(pi.hThread);
(void)WaitForSingleObject(pi.hProcess, INFINITE);
(void)GetExitCodeProcess(pi.hProcess, &dwExitCode);
(void)CloseHandle(pi.hProcess);
}
return 0 == dwExitCode;
}
创建新的控制台进程并等待返回结果以及获得控制台输出
说明:主程序与控制台程序之间的通讯方式是内核句柄继承。
DWORD RunCommandProcessor(const PTCHAR pszCmd, CString& strOutPut)
{
// TODO: Add your control notification handler code here
DWORD dwRet = ERROR_INVALID_FUNCTION;
CString strCurDir;
(void)GetModuleFileName(NULL, strCurDir.GetBuffer(MAX_PATH), MAX_PATH - 1);
strCurDir.ReleaseBuffer();
strCurDir = strCurDir.Left(strCurDir.ReverseFind(_T('\\')));
CString strCmdLine;
strCmdLine.Format(_T("%s\\%s"), strCurDir, pszCmd);
LOG(_T("%s"), strCmdLine);
PROCESS_INFORMATION pi = {0};
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES)};
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
STARTUPINFO si = {sizeof(STARTUPINFO)};
DWORD dwWaitRet = WAIT_FAILED;
HANDLE hRead = NULL;
HANDLE hWrite = NULL;
BOOL bRet = CreatePipe(&hRead, &hWrite, &sa, 0);
if (!bRet)
{
goto final;
}
GetStartupInfo(&si);
si.hStdError = hWrite;
si.hStdOutput = hWrite;
si.wShowWindow = SW_HIDE;
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
bRet = CreateProcess(NULL, (LPTSTR)(LPCTSTR)strCmdLine, NULL, NULL, TRUE,
NULL, NULL, NULL, &si, &pi); // TRUE:继承父进程句柄
if (!bRet)
{
goto final;
}
(void)CloseHandle(pi.hThread);
dwWaitRet = WaitForSingleObject(pi.hProcess, INFINITE);
(void)GetExitCodeProcess(pi.hProcess, &dwRet);
(void)CloseHandle(pi.hProcess);
// 在ReadFile之前要关掉,否则ReadFile一直等待写入
(void)CloseHandle(hWrite);
if (dwWaitRet == WAIT_FAILED)
{
goto final;
}
char buffer[4096] = {0}; // 没有考虑WCHAR
DWORD bytesRead = 0;
do
{
if (ReadFile(hRead, buffer, 4096, &bytesRead, NULL))
{
strOutPut += buffer;
}
else
{
break;
}
} while (TRUE);
// dwRet = ERROR_SUCCESS;
final:
(void)CloseHandle(hRead);
return dwRet;
}
应用程序关联控制台程序并显示输出
参照MSDN中的Console Functions。该组函数用于为当前进程创建一个控制台界面,具体用途不明,一般用来输出日志,但是似乎没有Debug View方便。
以输出日志为例,大致的使用方式是:
1.在‘App::InitInstance()’时调用‘AllocConsole();’分配一个控制台;
2.此时可以配置控制台,比如调用‘SetConsoleTitle(_T("Title"));’,或者其他改变控制台特性的API:‘SetConsoleWindowInfo’、‘SetCurrentConsoleFontEx’等;
3.需要向控制台写时:
HANDLE hdlWrite = GetStdHandle(STD_OUTPUT_HANDLE); //这里也可以使用STD_ERROR_HANDLE
TCHAR c[MAX_PATH] = _T("Hello world!\r\n");
BOOL bRet = WriteConsole(hdlWrite, c, _tcslen(c), NULL, NULL);
CloseHandle(hdlWrite);
4.需要从控制台读时:
TCHAR szBuffer[MAX_PATH] = {0};
DWORD dwCount = 0;
HANDLE hdlRead = GetStdHandle(STD_INPUT_HANDLE);
ReadConsole(hdlRead, szBuffer, MAX_PATH, &dwCount, NULL);
CloseHandle(hdlRead);
5.退出时:
BOOL bRet = FreeConsole();