C-C++ Code Example: Navigating Using Lookup Identifiers

 

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 navigates through the queue using the lookup identifiers of messages in the queue.

When navigating with lookup identifiers, keep the following in mind.

  • Receiving applications can start at the front of the queue, at the end of the queue, or at a specific message if the lookup identifier for that message is known.

  • Receiving applications can read the next message or a previous message by using the appropriate peek or receive method. This example starts at the front and navigates to the end of the queue.

  • There is no time-out parameter when reading messages synchronously.

For more information on lookup identifiers, see Navigating with Lookup Identifiers.

To navigate a queue using lookup identifiers

  1. Define the maximum number of properties and the property counter.

  2. Define the MQMSGPROPS structure.

  3. Specify the message properties to be retrieved. This example retrieves PROPID_M_LABEL, PROPID_M_LABEL_LEN, and PROPID_M_LOOKUPID. The maximum label length, including the string-terminating character, is MQ_MAX_MSG_LABEL_LEN (250 Unicode characters).

  4. Initialize the MQMSGPROPS structure.

  5. Call MQOpenQueue to read the messages in the queue.

  6. Call MQReceiveMessageByLookupId to read the first message in the queue. Note that in this call the dwLookupAction parameter is set to MQ_LOOKUP_PEEK_FIRST and the ullLookupId parameter is set to 0 (zero).

  7. In a loop structure, process the current message and then call MQReceiveMessageByLookupId to read the next message. Note that in this call the dwLookupAction parameter is set to MQ_LOOKUP_PEEK_NEXT and the ullLookupId parameter is set to lookup identifier of the previous call.

Note

The PROPID_M_LABEL_LEN property must be reset to its maximum value (MQ_MAX_MSG_LABEL_LEN) after each call to peek at a message. If the label length is not reset, an error is returned if the new message label is longer than the previous message label.

  1. Call MQCloseQueue to release resources used to open the queue.

Code Example

The following code example requires MSMQ 3.0.

HRESULT NavigateLookupId(  
                         LPCWSTR wszQueueFormatName  
                         )  
{  
  // Define the required parameters.  
  const int NUMBEROFPROPERTIES = 3;                  // Number of properties  
  DWORD cPropId = 0;                                 // Properties counter  
  HRESULT hr = MQ_OK;                                // Return code  
  HANDLE hQueue = NULL;                              // Queue handle  
  WCHAR wszLabelBuffer[MQ_MAX_MSG_LABEL_LEN];        // Label buffer  
  ULONGLONG ullLookupId;                             // Lookup identifier of the current message  
  
  // Define an MQMSGPROPS structure.  
  MQMSGPROPS msgProps;  
  MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];  
  MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];  
  HRESULT aMsgStatus[NUMBEROFPROPERTIES];  
  
  // Specify the message properties to be retrieved.  
  aMsgPropId[cPropId] = PROPID_M_LABEL_LEN;           // Property ID  
  aMsgPropVar[cPropId].vt =VT_UI4;                    // Type indicator  
  aMsgPropVar[cPropId].ulVal = MQ_MAX_MSG_LABEL_LEN;  // Label buffer size  
  cPropId++;  
  
  aMsgPropId[cPropId] = PROPID_M_LABEL;               // Property ID  
  aMsgPropVar[cPropId].vt = VT_LPWSTR;                // Type indicator  
  aMsgPropVar[cPropId].pwszVal = wszLabelBuffer;      // Label buffer  
  cPropId++;  
  
  aMsgPropId[cPropId] = PROPID_M_LOOKUPID;            // Property ID  
  aMsgPropVar[cPropId].vt = VT_UI8;                   // Type indicator  
  cPropId++;  
  
  // Initialize the MQMSGPROPS structure.  
  msgProps.cProp = cPropId;                           // Number of message properties.  
  msgProps.aPropID = aMsgPropId;                      // IDs of the message properties  
  msgProps.aPropVar = aMsgPropVar;                    // Values of the message properties  
  msgProps.aStatus  = aMsgStatus;                     // Error reports  
  
  // Open the queue to read messages.  
  hr = MQOpenQueue(  
                   wszQueueFormatName,                // Format name of the queue  
                   MQ_RECEIVE_ACCESS,                 // Access mode  
                   MQ_DENY_RECEIVE_SHARE,             // Share mode  
                   &hQueue                            // OUT: Queue handle  
                   );  
  if (FAILED(hr))  
  {  
    return hr;  
  }  
  
  // Peek at the first message in the queue.  
  hr = MQReceiveMessageByLookupId(  
                                  hQueue,                 // Queue handle  
                                  0,                      // No need for a lookup identifier  
                                  MQ_LOOKUP_PEEK_FIRST,   // Access mode  
                                  &msgProps,              // Message property structure  
                                  NULL,                   // No OVERLAPPED structure  
                                  NULL,                   // No callback function  
                                  MQ_NO_TRANSACTION       // Not in a transaction  
                                  );  
  
  while (SUCCEEDED(hr))  
  {  
  
   // Process the message.  
    wprintf(L"%s\n", msgProps.aPropVar[1].pwszVal);  
    aMsgPropVar[0].ulVal = MQ_MAX_MSG_LABEL_LEN;          // Reset the label buffer size.  
    ullLookupId = msgProps.aPropVar[2].uhVal.QuadPart;  
  
    // Peek at the next message using the current message lookup identifier.  
    hr = MQReceiveMessageByLookupId(  
                                    hQueue,               // Queue handle  
                                    ullLookupId,          // The lookup identifier  
                                    MQ_LOOKUP_PEEK_NEXT,  // Access mode  
                                    &msgProps,            // Message property structure  
                                    NULL,                 // No OVERLAPPED structure  
                                    NULL,                 // No callback function  
                                    MQ_NO_TRANSACTION     // Not in a transaction  
                                    );  
    }  
  
  // Close the queue.  
  hr = MQCloseQueue(hQueue);  
  
  return hr;  
}