C-C++ COM Code Example: Sending Messages to a Destination Queue Using a Destination Object

 

Applies To: Windows 10, Windows 7, Windows 8, Windows 8.1, Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server Technical Preview, Windows Vista

This example provides an application-defined function that sends a message to a single public or private destination queue on the local computer or a remote computer using an MSMQDestination object (introduced in MSMQ 3.0).

Note

Remote queues can be opened to send messages while offline. To do this, your application must either obtain and cache the format name of a remote queue while online or have the information needed to construct a direct format name for the queue. This example creates a direct format name from the computer name and queue name provided by the caller.

This example uses smart pointers to the following Message Queuing interfaces.

  • MSMQDestination: Represents the destination queue specified by the computer name and queue name provided by the caller.

  • MSMQMessage3: Represents the message.

To use smart pointers, your application must import Mqoa.dll. You can import this DLL using the #import directive and specify the MSMQ namespace.

#import "mqoa.dll"  
using namespace MSMQ;  

Before using any smart pointer, your application must call CoInitialize or CoInitializeEx to initialize the COM library. After the COM library is no longer needed, your application must call CoUnitialize. For more information, see Using Message Queuing COM Components in Visual C++ and C.

To send a message to a destination queue using a destination object

  1. Create smart pointers to MSMQDestination and IMSMQMessage3 interfaces.

  2. Create a direct format name for the queue from the computer name and queue name supplied by the caller. This function can be modified to receive a format name of any type from the caller.

Note

wcslen properly handles only null-terminated strings. This code example does not verify that the strings passed to it are null-terminated. It is the responsibility of the caller to ensure that the strings passed are null-terminated.

  1. Set the FormatName property of the MSMQDestination object to the direct format name and free the memory allocated for the format name buffer.

    Alternatively, except in the case of a remote private queue, you can create the path name of the queue from the computer name and queue name supplied by the caller, and set the PathName property of the MSMQDestination object using the following lines of code.

    // Create the path name of the queue.  
    WCHAR * wszPathName = NULL;  
    DWORD dwPathNameLength = 0;  
    dwPathNameLength = wcslen(wszComputerName) + wcslen(wszQueueName) + 2;  
    wszPathName = new WCHAR[dwPathNameLength];  
    if (wszPathName == NULL)  
    {  
      return MQ_ERROR_INSUFFICIENT_RESOURCES;  
    }  
    memset(wszPathName, 0, dwPathNameLength*sizeof(WCHAR));  
    // ************************************  
    // You must concatenate wszComputerName, "\", and wszQueueName into   
    // the wszPathName buffer.  
    // wszPathName = wszComputerName + "\" + wszQueueName  
    // If the path name is too long for the buffer, return FALSE.  
    // ************************************  
    
    // Set the PathName property of the MSMQDestination object to  
    // the path name created and free the memory allocated for the  
    // path name buffer.  
    pDest->PathName = wszPathName;  
    delete [] wszPathName;  
    

When the PathName property is set, Message Queuing must obtain the format name of the queue before opening it. The public format name of any public queue must be retrieved from the directory service, and the private format name of a local private queue can be obtained from information stored on the local computer.

  1. Set message properties. This procedure sets the MSMQMessage.Label property of the message to "Test Message".

  2. Call MSMQMessage.Send using the corresponding smart pointer to send the message to the destination queue. Note that when using an MSMQDestination object, Message Queuing implicitly opens the destination queues with send access.

  3. Call MSMQDestination.Close using the corresponding smart pointer to close the MSMQDestination object.

Code Example

The following code example requires MSMQ 3.0.

HRESULT SendToDest(  
                   WCHAR *wszComputerName,  
                   WCHAR *wszQueueName  
                   )  
{  
  HRESULT hr = S_OK;  
  
  // Validate the input strings.  
  if ((wszQueueName == NULL) || (wszComputerName == NULL))  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  try  
  {  
  
    // Create smart pointers to IMSMQDestination and IMSMQMessage3 interfaces.  
    IMSMQDestinationPtr pDest(L"MSMQ.MSMQDestination");  
    IMSMQMessage3Ptr pMsg(L"MSMQ.MSMQMessage");  
  
    // Create a direct format name for the queue.  
    WCHAR * wszFormatName = NULL;  
    DWORD dwFormatNameLength = 0;  
    const WCHAR * wszFormatStr = L"DIRECT=OS:%s\\%s" ;  
    dwBufferLength = wcslen(wszQueueName) + wcslen(wszComputerName) +   
                                         wcslen(wszFormatStr) - 4;  
  
    wszFormatName = new WCHAR[dwFormatNameLength];  
    if (wszFormatName == NULL)  
    {  
      return MQ_ERROR_INSUFFICIENT_RESOURCES;  
    }  
    memset(wszFormatName, 0, dwFormatNameLength*sizeof(WCHAR));  
    // ************************************  
    // You must concatenate "DIRECT=OS:",  wszComputerName, "\",   
    // and wszQueueName into the wszFormatName buffer.  
    // wszFormatName = "DIRECT=OS:" + wszComputerName + "\" +   
    // wszQueueName  
    // If the format name is too long for the buffer, return FALSE.  
    // ************************************  
  
    // Set the FormatName property of the MSMQDestination object to  
    // the direct format name created.  
    pDest->FormatName = wszFormatName;  
    delete [] wszFormatName;  
  
    // Set message properties, send the message, and close the MSMQDestination object.  
    //  
    pMsg->Label = L"Test Message";  
    pMsg->Send(pDest);   
    pDest->Close();  
  
  }  
  catch (const _com_error& comerr)   
  {  
    wprintf(L"Error Code = 0x%X\nError Description = %s\n",  
    comerr.Error(), (WCHAR *)comerr.Description() );  
    return comerr.Error();  
  }  
  return hr;  
}