使用ShellExecuteEx调用控制台程序或命令行,传入多个参数,并等待返回结果


// 封装函数
// 参数依次为:
// 执行程序的路径 (只对控制台程序等待有效)
// 传给执行程序的参数
// 执行程序环境目录
// 最大等待时间, 超过这个时间强行终止。 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/7303079http://yumiao.blog.sohu.com/130391827.html


后记:

    没怎么碰到过这样的需求。没必要阻塞在等待子进程上。进程通信方式也比较多。很多情况下用线程就够了,线程通信就更容易了。

    这原本只是公司项目中的一个网络通信并发数的压力测试程序。最早版本,使用线程模拟的,一个线程代表一个客户,并执行有关操作,挺方便的。普通机子上,来1万线程模拟1万用户,很容易。

    后来需求变了,要调用同事的一个dll的几个接口做某件事。容易,不就调用dll,增加一点功能吗,这还不是手到擒来。三下五除二,修改完毕。连接,登陆,通信都没问题,一切正常。当执行到一个接口时,发现所有线程都暂停干活,只有一个线程在那忙碌。这不对啊,其他线程怎么能偷懒观望呢。因为我的服务器也是大改了一番,我以为是我的服务器通信出了问题。左看右看,上改下改,情况还是一样。哥郁闷了,完全不知道原因。一天过去了,没什么头绪,完全觉得没什么道理。哥认为,最近可能比较疲惫,下班后早点回去好好休息下(我个人在精力充沛的情况下,工作状态最好,所以,不大喜欢长时间疲惫工作。)。第二天,细细整理头绪,觉得没道理可言,不应该。虽然,一直是比较信任同事的模块,但还是去问了下他的那个接口的一些情况。原来,是他的接口不支持多线程。因为,主要用在客户端,多线程有很多问题需要考虑,在时间匆忙的情况下,限定一个进程只能有一个有效操作。这个接口用在客户程序,一直表现很好,没想到会用在我这里。好吧,改测试程序吧,于是就产生了上面的需求,测试程序由多线程改为,每个多线程执行一个子进程去协调完成工作。测试程序是完成了。测试数量就大大减少了。原来可以达到1.1w模拟客户,现在到600,内存就有点吃紧了。唉。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值