概述
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 以 结尾的字符串
* @ 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"rn");
if (_pos == std::wstring::npos)
{
strCmd.append(L"rn");
}
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] = '