// 封装函数
// 参数依次为:
// 执行程序的路径 (只对控制台程序等待有效)
// 传给执行程序的参数
// 执行程序环境目录
// 最大等待时间, 超过这个时间强行终止。 INFINITE 无限等待
DWORD ExecAndWaitConsole(LPCTSTR lpszAppPath, LPCTSTR lpParameters, LPCTSTR lpszDirectory, DWORD dwMilliseconds)
{
SHELLEXECUTEINFO ShExecInfo = {0};
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = NULL;
ShExecInfo.lpFile = lpszAppPath;
ShExecInfo.lpParameters = lpParameters;
ShExecInfo.lpDirectory = lpszDirectory;
ShExecInfo.nShow = SW_HIDE;
ShExecInfo.hInstApp = NULL;
if (!ShellExecuteEx(&ShExecInfo))
{
return 0;
}
// 指定时间没结束
if (WaitForSingleObject(ShExecInfo.hProcess, dwMilliseconds) == WAIT_TIMEOUT)
{ // 强行杀死进程
TerminateProcess(ShExecInfo.hProcess, 0);
return 0; //强行终止
}
DWORD dwExitCode;
if (!GetExitCodeProcess(ShExecInfo.hProcess, &dwExitCode))
{
return 0;
}
return dwExitCode;
}
补充:
如何执行dos命令行,并等待返回。(关键是参数 /c )
parm = (boost::format("/c copy /b \"%s\"+\"%s\" \"%s\" ") % temp*** % temp*** % temp***).str(); result = ExecAndWaitConsole("cmd", parm.c_str(), temp.c_str(), INFINITE);
控制台程序:
// test int _tmain(int argc, _TCHAR* argv[]) { if (argc < 5) { return 0; } // 网盘地址 char ndiskUrl[512] = {0}; // 网盘账号 char ndiskUser[128] = {0}; // 网盘用户key char ndiskKey[128] = {0}; char filename[256] = {0}; // 第一个参数(索引为0)是程序路径 sprintf(ndiskUrl, "%s", argv[1]); sprintf(ndiskUser, "%s", argv[2]); sprintf(ndiskKey, "%s", argv[3]); sprintf(filename, "%s", argv[4]); // ... return 0; }
// 使用
char parm[2048] = {0}; sprintf(parm, _T("%s %s %s %s"), ndisk.ndiskUrl, ndisk.ndiskUser, ndisk.ndiskKey, filename); CString path; GetModuleFileName(NULL,path.GetBufferSetLength(MAX_PATH+1),MAX_PATH); path.ReleaseBuffer(); int pos = path.ReverseFind('\\'); path = path.Left(pos); if (WinExecAndWait32(path + "\\Test.exe", parm, NULL, INFINITE ) == NDISK_API_OK) { // sussess } else { // fail }
参考:http://blog.csdn.net/mnorst/article/details/7303079,http://yumiao.blog.sohu.com/130391827.html
后记:
没怎么碰到过这样的需求。没必要阻塞在等待子进程上。进程通信方式也比较多。很多情况下用线程就够了,线程通信就更容易了。
这原本只是公司项目中的一个网络通信并发数的压力测试程序。最早版本,使用线程模拟的,一个线程代表一个客户,并执行有关操作,挺方便的。普通机子上,来1万线程模拟1万用户,很容易。
后来需求变了,要调用同事的一个dll的几个接口做某件事。容易,不就调用dll,增加一点功能吗,这还不是手到擒来。三下五除二,修改完毕。连接,登陆,通信都没问题,一切正常。当执行到一个接口时,发现所有线程都暂停干活,只有一个线程在那忙碌。这不对啊,其他线程怎么能偷懒观望呢。因为我的服务器也是大改了一番,我以为是我的服务器通信出了问题。左看右看,上改下改,情况还是一样。哥郁闷了,完全不知道原因。一天过去了,没什么头绪,完全觉得没什么道理。哥认为,最近可能比较疲惫,下班后早点回去好好休息下(我个人在精力充沛的情况下,工作状态最好,所以,不大喜欢长时间疲惫工作。)。第二天,细细整理头绪,觉得没道理可言,不应该。虽然,一直是比较信任同事的模块,但还是去问了下他的那个接口的一些情况。原来,是他的接口不支持多线程。因为,主要用在客户端,多线程有很多问题需要考虑,在时间匆忙的情况下,限定一个进程只能有一个有效操作。这个接口用在客户程序,一直表现很好,没想到会用在我这里。好吧,改测试程序吧,于是就产生了上面的需求,测试程序由多线程改为,每个多线程执行一个子进程去协调完成工作。测试程序是完成了。测试数量就大大减少了。原来可以达到1.1w模拟客户,现在到600,内存就有点吃紧了。唉。
|