The MSMQ Component Set

The two most important components in the MSMQ set are MSMQMessage and MSMQQueue. Unsurprisingly, the former represents a message, whilst the latter represents a queue. As it happens though, you never actually instantiate a MSMQQueue component; to do this, you need to use one of the methods of the MSMQQueueInfo interface. The MSMQQueueInfo is a component that describes the static aspects of a queue, whereas the MSMQQueue component describes the dynamic aspects of it.

You can instantiate your own MSMQQueueInfo object, or you can get one by enumerating through a list by using a MSMQQueueInfos object. You can’t, however, instantiate a MSMQQueueInfos object: the only way to get hold of one of these is by using the LookupQueue() method of a MSMQQuery object.

Confused? Don’t worry — it’s a lot more straightforward in practice. Let’s put together our SimpleMail application. We’ll start off by including the MSMQ header file at the top of the SimpleMailDlg.h file and — because we'll be using the Visual C++ compiler COM support classes — setting up a few smart pointer typedefs for the interfaces that we'll be using. (The MSMQ library and header files can be found in the sdk folder of your MSMQ installation directory):

#include <comdef.h>   // Compiler COM support classes
#define SMARTPTR_TYPEDEF(x)   \
   typedef _com_ptr_t<_com_IIID<x, &IID_##x> > x##Ptr;

#include <mqoai.h>   // MSMQ interfaces/GUIDs
SMARTPTR_TYPEDEF(IMSMQQueueInfos);
SMARTPTR_TYPEDEF(IMSMQQueueInfo);
SMARTPTR_TYPEDEF(IMSMQQueue);
SMARTPTR_TYPEDEF(IMSMQQuery);
SMARTPTR_TYPEDEF(IMSMQMessage);

To get the full definitions of the GUIDs from mqoai.h, we'll also need to #include this file in StdAfx.cpp after including initguid.h.

// Get the definitions of the MSMQ GUIDs (to avoid linker errors)
#include <initguid.h>
#include <mqoai.h>

The first change that we make is at the end of OnInitDialog():

   SetIcon(m_hIcon, FALSE);      // Set small icon

   // Make sure COM has been initialized in CSimpleMailApp::InitInstance()
   // with a call to AfxOleInit()
   ShowQueues();
   OnRefresh();
   
   return TRUE;  // return TRUE  unless you set the focus to a control
}

Let’s take a look at that ShowQueues() function; this is the piece of code that populates the three combo boxes that contain lists of the available queues.

void CSimpleMailDlg::ShowQueues()
{
   // Create query
   IMSMQQueryPtr pQuery;
   HRESULT hr = pQuery.CreateInstance(CLSID_MSMQQuery, NULL, CLSCTX_SERVER);
   if (FAILED(hr))
   {
      DisplayComError(_T("Failed to create message query"), hr);
      return;
   }

   // Get information on all queues
   VARIANT vEmpty;
   vEmpty.vt = VT_ERROR;
   IMSMQQueueInfosPtr pInfos;
   hr = pQuery->LookupQueue(&vEmpty, &vEmpty, &vEmpty, &vEmpty, &vEmpty,
                            &vEmpty, &vEmpty, &vEmpty, &vEmpty, &pInfos);
   if (FAILED(hr))
   {
      DisplayComError(_T("Failed to look up queues"), hr);
      return;
   }

   pInfos->Reset();

   CComboBox* pOutgoing = ComboPtr(IDC_OUTGOING); // ComboPtr() returns
   CComboBox* pIncoming = ComboPtr(IDC_INCOMING); // a CComboBox* when given
   CComboBox* pAdmin = ComboPtr(IDC_ADMIN);       // a resource ID

   pOutgoing->ResetContent();
   pIncoming->ResetContent();
   pAdmin->ResetContent();

   // Loop through queues, extracting path names
   while (1)
   {
      IMSMQQueueInfoPtr pInfo;
      pInfos->Next(&pInfo);

      if (pInfo == NULL)
         break;

      BSTR bstrQueue;
      pInfo->get_PathName(&bstrQueue);
      CString csQueue = bstrQueue;
      SysFreeString(bstrQueue);

      pOutgoing->AddString(csQueue);
      pIncoming->AddString(csQueue);
      pAdmin->AddString(csQueue);
   }

   pOutgoing->SetCurSel(0);
   pIncoming->SetCurSel(0);
   pAdmin->SetCurSel(0);
}

OK, that’s how we get a list of the pathnames of all the available queues; how do we actually send a message to one of them?

© 1998 by Wrox Press. All rights reserved.