我需要开始编写一些MSMQ代码,它将与其他机器上的WCF代码进行交互.有MSMQ经验的人是否使用直接C与使用COM对MSMQ的优缺点提出建议?
解决方法
其实你不必决定.你可以结合起来.
以下是完整发送/ recv实现的代码示例.
如果你改进它,请告诉我……
h文件:
#pragma once
#include <tchar.h>
// ==========================================================================
// MSMQWrapper - wrappes the COM object used to send and receive messages through the MSMQ
class CMSMQWrapper
{
HANDLE m_hQ;
public:
CMSMQWrapper()
{
m_hQ= INVALID_HANDLE_VALUE;
::CoInitializeEx(NULL,COINIT_MULTITHREADED);
}
~CMSMQWrapper()
{
::CoUninitialize();
}
bool InitLocalQueue (const WCHAR* wczQueueName ); // [i] .\private$\queue_name
bool InitDestQueue (const WCHAR* wczDestQueueName ); // [i] comp_name\private$\queue_name
bool ReadQueue (const WCHAR* wczQueueName,// [i]
BYTE* pBuf,// [i]
size_t nBufLen,// [i]
int& nBytesRead ); // [o]
bool SendToDestQueue(const BYTE* pBuf,size_t nBufLen );
};
cpp文件:
#include "stdafx.h"
#include "msmqwrap.h"
#include <windows.h>
#include <AtlBase.h>
#import "mqoa.dll" named_guids // no_namespace
#pragma comment (lib,"Mqrt.lib")
#include "mq.h"
using namespace MSMQ;
// ==========================================================================
// CMSMQWrapper
// ==========================================================================
bool CMSMQWrapper::InitLocalQueue(const WCHAR* wczQueueName)
{
CComQIPtr<imsMQQueueInfo,&IID_imsMQQueueInfo> ipQueueInfo;
HRESULT hr= ::CoCreateInstance(CLSID_MSMQQueueInfo,NULL,CLSCTX_SERVER,IID_imsMQQueueInfo,(void**)(&ipQueueInfo.p) );
if (S_OK != hr)
return false;
hr= ipQueueInfo->put_PathName(_bstr_t(wczQueueName));
if (S_OK != hr)
return false;
hr= ipQueueInfo->put_Label(_bstr_t(wczQueueName));
if (S_OK != hr)
return false;
VARIANT vtFalse;
Variantinit(&vtFalse);
vtFalse.vt = VT_BOOL;
vtFalse.boolVal= FALSE ;
try
{
hr= ipQueueInfo->Create(&vtFalse,&vtFalse);
}
catch (_com_error& er)
{
if (MQ_ERROR_QUEUE_EXISTS == er.Error()) // queue already exists
hr= S_OK;
else
{
// report error - Failed receiving,(WCHAR*)er.Description()
return false;
}
}
return true;
}
// --------------------------------------------------------------------------
bool CMSMQWrapper::ReadQueue(const WCHAR* wczQueueName,// [i]
BYTE* pBuf,// [i]
size_t nBufLen,// [i]
int& nBytesRead ) // [o]
{
// set value of ReceiveTimout parameter
_variant_t vtReceiveTimeout;
vtReceiveTimeout= (long)INFINITE;
try
{
imsMQQueueInfoPtr qinfo("MSMQ.MSMQQueueInfo");
qinfo->PathName= wczQueueName;
imsMQQueuePtr qRec;
qRec= qinfo->Open(MQ_RECEIVE_ACCESS,MQ_DENY_NONE); // open queue to retrieve message
// retrieve messages from queue
imsMQMessagePtr msgRec("MSMQ.MSMQMessage");
msgRec= qRec->Receive(&vtMissing,&vtMissing,&vtReceiveTimeout);
if (NULL == msgRec)
{
nBytesRead= 0; // there are no messages in the queue
return true;
}
nBytesRead = msgRec->BodyLength;
_variant_t recVariant= msgRec->Body ;
// close queue
qRec->Close();
SAFEARRAY* psa= recVariant.parray;
nBytesRead = __min(psa->rgsabound->cElements,nBufLen);
for (LONG ind= 0; ind< nBytesRead; ind++)
SafeArrayGetElement(psa,&ind,&pBuf[ind]);
return true;
}
catch (_com_error comerr)
{
// report error - Failed receiving,(WCHAR*)comerr.Description());
return false;
}
}
// --------------------------------------------------------------------------
bool CMSMQWrapper::InitDestQueue(const WCHAR* wczDestQueueName) // comp_name\private$\queue_name
{
// validate the input strings
if (NULL == wczDestQueueName)
return false;
// create a direct format name for the queue
WCHAR wczFormatName[1000];
str_cat(wczFormatName,1000,L"DIRECT=OS:",wczDestQueueName);
HRESULT hr;
hr = ::MQOpenQueue(wczFormatName,MQ_SEND_ACCESS,MQ_DENY_NONE,&m_hQ);
if (MQ_OK != hr) //MQ_ERROR_QUEUE_NOT_FOUND
return false;
return true;
}
// --------------------------------------------------------------------------
bool CMSMQWrapper::SendToDestQueue(const BYTE* pBuf,size_t nBufLen)
{
MQMSGPROPS MsgProps ;
const UINT _nProps= 1 ;
MSGPROPID aPropId [_nProps];
PROPVARIANT aVariant[_nProps];
aPropId [0] = PROPID_M_BODY ; // msg to send
aVariant[0].vt = VT_VECTOR|VT_UI1;
aVariant[0].caub.pElems= (BYTE*)pBuf ;
aVariant[0].caub.cElems= nBufLen ;
MsgProps.cProp = _nProps ; // number of props to set
MsgProps.aPropID = aPropId ;
MsgProps.aPropVar = aVariant ;
MsgProps.aStatus = 0 ;
if (MQ_OK != ::MQSendMessage(m_hQ,&MsgProps,MQ_NO_TRANSACTION))
return false;
return true;
}