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;
};