MFC-双管道

双管道比但管道复杂一点,但是功能强大,能更快速的处理进程间的通信.

还是以单管道的例子,稍加修改即可

1.定义两个成员变量.

    HANDLE m_hInReadPipe;//读取输入管道的内容
    HANDLE m_hOutWritePipe;//把命令输出到输出管道

2.在构造函数中创建管道和进程

HANDLE hInWritePipe = nullptr;//把内容写到输入管道
    HANDLE hOutReadPipe = nullptr;//从输出管道里读取命令
                               //管道的安全属性
    SECURITY_ATTRIBUTES sa = { 0 };
    sa.nLength = sizeof(sa);
    sa.bInheritHandle = TRUE;//句柄可继承
    sa.lpSecurityDescriptor = nullptr;//安全描述,设为null

                                      //创建管道
    //创建输出管道,就是把命令从编辑框中输出到命令框
    BOOL bCreateOutPipe = CreatePipe(&hOutReadPipe, &m_hOutWritePipe, &sa, 0);
    if (!bCreateOutPipe)
    {
        AfxMessageBox(TEXT("创建输出管道失败!"));
        return;
    }
    //创建输入管道,命令框内容输入到编辑框中
    BOOL bCreateInPipe = CreatePipe(&m_hInReadPipe, &hInWritePipe, &sa, 0);
    if (!bCreateOutPipe)
    {
        AfxMessageBox(TEXT("创建输入管道失败!"));
        return;
    }

    //进程信息结构
    PROCESS_INFORMATION pi = { 0 };
    //启动信息
    STARTUPINFO si = { 0 };
    si.cb = sizeof(STARTUPINFO);
    //因为是双管道,所以命令从输出管道中读取
    si.hStdInput = hOutReadPipe;
    //输出到输入管道中
    si.hStdOutput = si.hStdError = hInWritePipe;
    si.wShowWindow = SW_HIDE;//隐藏进程窗口
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

    //创建进程 ,一开始就把命令框创建出来,szCmdLine是全局变量,初始化为cmd
    BOOL bCreateProc = CreateProcess(nullptr, szCmdLine, nullptr,
        nullptr, TRUE, 0, nullptr, nullptr, &si, &pi);
    if (!bCreateProc)
    {
        AfxMessageBox(TEXT("创建进程失败!"));
        return;
    }
    //不需要这两个句柄,关掉他们
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    //用完后关掉管道的另一端
    CloseHandle(hInWritePipe);
    CloseHandle(hOutReadPipe);

3.输出命令,读内容

    //获取命令
    GetDlgItemText(IDC_EDIT_CMD, szCmdLine, MAX_PATH * 2);
    //添加换行符(回车),否则命令不能执行
    strcat(szCmdLine, "\n");
    //把命令输出到命令框
    if (!WriteFile(m_hOutWritePipe, szCmdLine, strlen(szCmdLine), nullptr, nullptr))
        return;

    //给命令执行的时间,像ping这种命令,2秒是执行不完的,所以只能读回一部分数据
    Sleep(2000);

    //创建成功后,把管道的内容读取出来
    //注意,只能用ASCII编码格式读,因为命令行窗口的内容都是ASCII编码的
    //如果CString TCHAR 来读会乱码
    char szBuffer[4096] = { 0 };
    DWORD dwRead = 0;
    //检查输入管道里面是否还有内容
    while (PeekNamedPipe(m_hInReadPipe,szBuffer,4096,&dwRead,nullptr,0)
        && dwRead >0) 
    {
        memset(szBuffer, 0, sizeof(szBuffer));
        ReadFile(m_hInReadPipe, szBuffer, dwRead, nullptr, nullptr);
        m_content += szBuffer;
    }
    //显示内容
    UpdateData(FALSE);

4.关闭管道句柄

CMFCTESTDlg::~CMFCTESTDlg() { CloseHandle(m_hInReadPipe);
    CloseHandle(m_hOutWritePipe);
}

这要就能运行的时候打开一个进程,然后直接通过管道输出命令,就不用每执行一次就创建一个新的进程.

要注意的是,给命令添加换行符的时候,这个换行符不能是unicode字符,因为命令窗口是ASCII码的,所以乱码后命令不能识别.
解决方法:项目->属性->字符集->改为未设置,这样TCHAR就会自动转换为char型,就能正确识别换行符.

你可能感兴趣的:(mfc,进程通信,双管道)