进程间通信 - 匿名管道

IPC通信其中的一种,匿名管道适用于父子关系之间的进程通信,匿名管道其实就是一段共享内存,只不过系统为这段内存进行了特殊的自己流处理。


              写接口 --> |==================| --> 读接口


以下以双管道的机制实现与CMD之间的通信


说明:KBundle为参数传递类http://blog.csdn.net/yyw610879290/article/details/28153977


消息读取回调类

//
//
// @ File   : icmdshellcallback.h
// @ Data   : 2014-07-26 23:11:12
// @ Remark : CmdShell的回调接口
//
//

#ifndef __DEFINE_CMD_SHELL_PIPE_ICMDSHELLCALLBACK_H_
#define __DEFINE_CMD_SHELL_PIPE_ICMDSHELLCALLBACK_H_

class KBundle;

//

class ICmdShellCallBack
{
public:
    virtual void NotifyIOShell(KBundle* pResult) = 0;
};

#endif ///> __DEFINE_CMD_SHELL_PIPE_ICMDSHELLCALLBACK_H_

//


cmdshell定义

//
//
// @ File   : kcmdshellcm.h
// @ Data   : 2014-07-26 23:44:18
// @ Remark : 
//
//

#ifndef __DEFINE_CMD_SHELL_PIPE__KCMDSHELLCM_H_
#define __DEFINE_CMD_SHELL_PIPE__KCMDSHELLCM_H_

#include <string>
#include <Windows.h>
#include "icmdshellcallback.h"

#define RESULT_PARAM            (L"result")

//

class KCmdShellCM
{
public:
    typedef struct _PIPE_HANDLE     ///>pipe handles
    {
        HANDLE          hRead;      ///> read from pipe
        HANDLE          hWrite;     ///> write to pipe

        _PIPE_HANDLE()
            : hRead(NULL)
            , hWrite(NULL)
        {

        }

    }PIPE_HANDLE, *PPIPE_HANDLE;

public:
    KCmdShellCM();
    ~KCmdShellCM();

public:
    /**
    * @ brief   : 开启与CMD的通信
    * @ param   : [IN] pCmdShellCall 读取数据之后通知的对象
    * @ param   : [IN] dwTime 每隔多少毫秒读取一次
    * @ return  : TRUE 开启成功
    **/
    BOOL StartCmdShellCM(
        __in ICmdShellCallBack* pCmdShellCall, 
        __in DWORD dwTime = 1000
        );
    
    /**
    * @ brief   : 输入命令
    * @ param   : [IN] lpszCmd 以\0结尾的字符串
    * @ return  : TRUE 发送成功
    * @ comment : 
    **/
    BOOL InputToCmdShell(__in LPCWSTR lpszCmd);
    
    /**
    * @ brief   : 停止与CMD的通信
    **/
    void StopCmdShellCM();

private:
    BOOL _InitPipe();
    BOOL _InitCmdProcess();
    BOOL _InitReadThread();
    void _UnInitPipe();
    
    void _ThreadFucn();

    void _RepairCommand(LPCWSTR lpszCmd, std::string& strResult);
    
    std::wstring _ConvertA2W(PCHAR pszBuf);
    std::string  _ConvertW2A(LPCWSTR lpszCmd);

private:
    static unsigned __stdcall ThreadFunction(void* pPrarm);

private:
    DWORD                           m_dwTimeout;        ///> wait

    HANDLE                          m_hEvent;           ///> stop event
    HANDLE                          m_hThread;          ///> read thread

    PIPE_HANDLE                     m_hRWCmd;           ///> cmd
    PIPE_HANDLE                     m_hRWSelf;          ///> program
    
    ICmdShellCallBack*              m_pCmdShellCall;    ///> receive data to notify

    static const int                MAX_BUFFER = MAX_PATH * 4;
};

#endif ///> __DEFINE_CMD_SHELL_PIPE__KCMDSHELLCM_H_

//


cmdshellcm实现

//
//
// @ File   : kcmdshellcm.cpp
// @ Data   : 2014-07-30 11:14:12
// @ Remark : 
//
//

#include "stdafx.h"
#include "kbundle.h"
#include "kcmdshellcm.h"

#define DESTROY_HANDLE(handle)\
    if (handle != NULL)\
    {\
        ::CloseHandle(handle);\
        handle = NULL;\
    }

#define SAFE_HANDLE(handle)\
    handle != NULL


//

KCmdShellCM::KCmdShellCM()
    : m_hEvent(NULL)
{
}

KCmdShellCM::~KCmdShellCM()
{
}

BOOL KCmdShellCM::StartCmdShellCM(__in ICmdShellCallBack* pCmdShellCall, 
                                  __in DWORD dwTime /* = 1000 */)
{
    BOOL bRet = FALSE;

    if (pCmdShellCall == NULL)
    {
        goto Exit0;
    }

    m_dwTimeout     = dwTime;
    m_pCmdShellCall = pCmdShellCall;

    if (!_InitPipe() || !_InitCmdProcess() || !_InitReadThread())
    {
        goto Exit0;
    }

    bRet = TRUE;

Exit0:
    return bRet;
}

BOOL KCmdShellCM::InputToCmdShell(LPCWSTR lpszCmd)
{
    BOOL bRet = FALSE;
    std::string strResult;
    
    if (lpszCmd == NULL)
    {
        goto Exit0;
    }
   
    _RepairCommand(lpszCmd, strResult);
    
    if (strResult.empty() || !SAFE_HANDLE(m_hRWSelf.hWrite))
    {
        goto Exit0;
    }
     
    DWORD dwWrite = 0;

    bRet = ::WriteFile(
            m_hRWSelf.hWrite, 
            strResult.c_str(), 
            strResult.size(), 
            &dwWrite, 
            NULL
            );

Exit0:
    return bRet;
}

void KCmdShellCM::StopCmdShellCM()
{
    _UnInitPipe();
}

BOOL KCmdShellCM::_InitPipe()
{
    BOOL bRet = FALSE;
    SECURITY_ATTRIBUTES sa = {sizeof(sa), NULL, TRUE};
    
    ///> cmd --> |---------| --> self
    if (!::CreatePipe(&m_hRWSelf.hRead, &m_hRWCmd.hWrite, &sa, 0))   
    {
        goto Exit0;
    }

    ///> self --> |---------| --> cmd
    if (!::CreatePipe(&m_hRWCmd.hRead, &m_hRWSelf.hWrite, &sa, 0))
    {
        goto Exit0;
    }

    bRet = SAFE_HANDLE(m_hRWSelf.hRead)
            && SAFE_HANDLE(m_hRWSelf.hWrite)
            && SAFE_HANDLE(m_hRWCmd.hRead)
            && SAFE_HANDLE(m_hRWCmd.hWrite);

Exit0:
    if (!bRet)
    {
        DESTROY_HANDLE(m_hRWSelf.hRead);
        DESTROY_HANDLE(m_hRWSelf.hWrite);

        DESTROY_HANDLE(m_hRWCmd.hRead);
        DESTROY_HANDLE(m_hRWCmd.hWrite);
    }

    return bRet;
}

BOOL KCmdShellCM::_InitCmdProcess()
{
    BOOL bRet = FALSE;
    WCHAR szParam[MAX_PATH + 1] = {0};

    if (::GetSystemDirectoryW(szParam, MAX_PATH) == 0
        || wcslen(szParam) == 0)
    {
        return bRet;
    }

    StrCatW(szParam, L"\\cmd.exe");

    PROCESS_INFORMATION pi = {NULL};
    STARTUPINFOW si = {sizeof(si)};

    si.dwFlags      = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.wShowWindow  = SW_HIDE;
    si.hStdError    = m_hRWCmd.hWrite;
    si.hStdOutput   = m_hRWCmd.hWrite;
    si.hStdInput    = m_hRWCmd.hRead;
        
    bRet = ::CreateProcessW(
        NULL, szParam, 
        NULL, NULL, 
        TRUE, 
        CREATE_NEW_CONSOLE, 
        NULL, NULL, 
        &si, &pi
        );
    
    DESTROY_HANDLE(pi.hThread);
    DESTROY_HANDLE(pi.hProcess);

    return bRet;
}

BOOL KCmdShellCM::_InitReadThread()
{
    m_hEvent = ::CreateEventW(NULL, FALSE, FALSE, NULL);
    m_hThread = (HANDLE)_beginthreadex(NULL, 0, ThreadFunction, this, 0, NULL);

    return SAFE_HANDLE(m_hEvent) && SAFE_HANDLE(m_hThread);
}

void KCmdShellCM::_UnInitPipe()
{
    ::SetEvent(m_hEvent);
    if (::WaitForSingleObject(m_hThread, 1000) == WAIT_TIMEOUT)
    {
        ::SuspendThread(m_hThread);
        ::TerminateThread(m_hThread, 0);
    }

    DESTROY_HANDLE(m_hThread);
    DESTROY_HANDLE(m_hEvent);
}

void KCmdShellCM::_RepairCommand(LPCWSTR lpszCmd, std::string& strResult)
{
    std::wstring strCmd(lpszCmd);
    std::wstring::size_type _pos = strCmd.rfind(L"\r\n");

    if (_pos == std::wstring::npos)
    {
        strCmd.append(L"\r\n");
    }
    
    strResult = _ConvertW2A(strCmd.c_str());
}

void KCmdShellCM::_ThreadFucn()
{
    if (m_pCmdShellCall == NULL
        || m_hRWSelf.hRead == NULL)
    {
        return;
    }

    DWORD dwRead = 0;
    DWORD dwWait = WAIT_FAILED;
    char szBuf[MAX_BUFFER + 1] = {0};
    
    do 
    {
        dwWait = ::WaitForSingleObject(m_hEvent, m_dwTimeout);

        if (dwWait == WAIT_OBJECT_0 
            || dwWait == WAIT_FAILED)
        {
            break;
        }
        
        dwRead = 0;
        ZeroMemory(szBuf, sizeof(szBuf));
        ::ReadFile(m_hRWSelf.hRead, szBuf, MAX_BUFFER, &dwRead, NULL);
        
        if (dwRead < MAX_BUFFER)
        {
            szBuf[dwRead] = '\0';
        }

        KBundle kbResult;
        std::wstring strResult = _ConvertA2W(szBuf);

        kbResult.PutItem(RESULT_PARAM, strResult.c_str());
        m_pCmdShellCall->NotifyIOShell(&kbResult);

    } while (TRUE);
}

std::wstring KCmdShellCM::_ConvertA2W(PCHAR pszBuf)
{
    USES_CONVERSION;

    return A2W(pszBuf);
}

std::string KCmdShellCM::_ConvertW2A(LPCWSTR lpszCmd)
{
    USES_CONVERSION;

    return W2A(lpszCmd);
}

unsigned __stdcall KCmdShellCM::ThreadFunction(void* pPrarm)
{
    KCmdShellCM* pThis = static_cast<KCmdShellCM*>(pPrarm);

    if (pThis != NULL)
    {
        pThis->_ThreadFucn();
    }

    return 0;
}

//


使用示例:

class KCMTest
    : public ICmdShellCallBack
{
public:
    KCMTest()
    {
    }

    ~KCMTest()
    {
    }

public:
    void Init()
    {
        m_cmdShell.StartCmdShellCM(this);
    }

    void Input(LPCWSTR lpszCmd)
    {
        m_cmdShell.InputToCmdShell(lpszCmd);
    }

    void UnInit()
    {
        m_cmdShell.StopCmdShellCM();
    }

private:    ///>ICmdShellCallBack
    virtual void NotifyIOShell(KBundle* pResult) 
    {

    }
    
private:
    KCmdShellCM         m_cmdShell;
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值