获取CMD执行结果——匿名管道

实现原理:

  管道是一种在进程间共享数据的机制,其实质是一段共享内存。Windows系统为这段共享的内存设计使用数据流I/O的方式来访问。一个进程读,另一个进程写,这类似于一个管道的两端,因此这种进程间的通信方式称为“管道”。管道分为匿名管道和命名管道。匿名管道只能在父子进程间进行通信,不能在网络间通信,而且数据传输是单向的,只能一端写,另一端读。命名管道可以在任意进程间通信,通信是双向的,任意一端都可读可写,但是在同一时间只能有一端读、一端写。创建命名管道的方式可以获取CMD执行结果的输出内容

实现过程:

  (1).调用函数CreatePipe创建匿名管道,获取管道数据读取句柄和管道数据写入句柄。

  (2).创建新进程(进程属性为窗口隐藏、窗口的缓存句柄设置为上面得到的管道数据写入句柄)

  (3).调用函数WaitForSingleObject等待命令执行完毕

  (4).调用ReadFile函数根据匿名管道的数据读取句柄从匿名管道的缓冲区中读取数据

  (5).关闭句柄,释放资源

实现代码:

    //************************************
    // 函数名:CCmdDlg::PipeCmd
    // 返回类型:BOOL
    // 功能:    执行CMD命令, 并获取执行结果数据
    // 参数1:char *pszCmd    cmd命令
    // 参数2:char *pszResultBuffer    接收CMD结果的缓冲区
    // 参数3:DWORD dwResultBufferSize    缓冲区大小(缓冲区要大点,不然接收到的结果不全)
    //************************************
BOOL CCmdDlg::PipeCmd(char *pszCmd, char *pszResultBuffer, DWORD dwResultBufferSize)
{
    SECURITY_ATTRIBUTES securityAttributes = { 0 };
    // 设定管道的安全属性
    securityAttributes.bInheritHandle = TRUE;
    securityAttributes.nLength = sizeof(securityAttributes);
    securityAttributes.lpSecurityDescriptor = NULL;

    // 创建匿名管道
    HANDLE hReadPipe = NULL;
    HANDLE hWritePipe = NULL;
    BOOL bRet = ::CreatePipe(&hReadPipe, &hWritePipe, &securityAttributes, 0);
    if (FALSE == bRet)
    {
        MessageBox(_T("CreatePipe Error"));
        return FALSE;
    }

    STARTUPINFO si = { 0 };
    // 设置新进程参数
    si.cb = sizeof(si);
    si.hStdError = hWritePipe;
    si.hStdOutput = hWritePipe;
    si.wShowWindow = SW_HIDE;
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    // 创建新进程执行命令, 将执行结果写入匿名管道中
    PROCESS_INFORMATION pi = { 0 };
    USES_CONVERSION;
    bRet = ::CreateProcess(NULL, A2W(pszCmd), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    if (FALSE == bRet)
    {
        MessageBox(_T("CreateProcess Error"));
    }

    // 等待命令执行结束
    ::WaitForSingleObject(pi.hThread, INFINITE);
    ::WaitForSingleObject(pi.hProcess, INFINITE);

    // 从匿名管道中读取结果到输出缓冲区
    ::RtlZeroMemory(pszResultBuffer, dwResultBufferSize);
    ::ReadFile(hReadPipe, pszResultBuffer, dwResultBufferSize, NULL, NULL);

    // 关闭句柄, 释放内存
    ::CloseHandle(pi.hThread);
    ::CloseHandle(pi.hProcess);
    ::CloseHandle(hWritePipe);
    ::CloseHandle(hReadPipe);

    return TRUE;
}

猜你喜欢

转载自www.cnblogs.com/ndyxb/p/12913476.html