C-C++ Code Example: Reading Messages in the Dead-Letter Queue

 

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 synchronously reads all the messages in the dead-letter queue of the local computer.

This example receives the computer GUID and uses it to generate the machine format name needed to open the dead-letter queue for reading messages. A machine format name cannot be used to open a queue if there is no connection to the directory service.

For more information on machine format names, see Machine and Connector Format Names.

In MSMQ 2.0 and later, this function can be modified to receive the computer name and generate the direct format name of the dead-letter queue. A direct format name can be used to open the queue in workgroup mode and in offline mode.

To read message in the dead-letter queue

  1. Define the MQMSGPROPS structure.

  2. Specify the message properties you want to retrieve.

  3. Initialize the MQMSGPROPS structure.

  4. Generate the format name of the dead-letter queue.

  5. Call MQOpenQueue to open the dead-letter queue with receive access.

  6. Call MQReceiveMessage and synchronously read all the messages in the dead-letter queue.

  7. Call MQCloseQueue to close the dead-letter queue and free resources.

Code Example

The following code example can be run on all versions of Message Queuing.

HRESULT ReadingComputerDeadletter(  
                                  LPCWSTR wszComputerId  
                                  )  
{  
  
  // Validate the input string.  
  if (wszComputerId == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  
  // Define the maximum total number of message properties and a property counter.  
  const int NUMBEROFPROPERTIES = 5;  
  DWORD cPropId = 0;  
  
  // Define the message property structure.  
  MQMSGPROPS MsgProps;  
  MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];  
  MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];   
  HRESULT aMsgStatus[NUMBEROFPROPERTIES];  
  
  HRESULT hr = MQ_OK;  
  
  // Retrieve message identifier.  
  unsigned char bMsgId[PROPID_M_MSGID_SIZE];  
  aMsgPropId[cPropId] = PROPID_M_MSGID;  
  aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1;  
  aMsgPropVar[cPropId].caub.cElems = PROPID_M_MSGID_SIZE;  
  aMsgPropVar[cPropId].caub.pElems = bMsgId;  
  cPropId++;  
  
  // Initialize the MQMSGPROPS structure.  
  MsgProps.cProp = cPropId;  
  MsgProps.aPropID = aMsgPropId;  
  MsgProps.aPropVar = aMsgPropVar;  
  MsgProps.aStatus = aMsgStatus;  
  
  // Compose the dead-letter queue format name.  
  WCHAR wszFormatName[60] = {0};  
  // ************************************  
  // You must concatenate "MACHINE=", wszComputerId, and ";DEADLETTER"  
  // into the wszFormatName buffer.  
  // wszFormatName = "MACHINE=" + wszComputerId + ";DEADLETTER"  
  // If the format name is too long for the buffer, return FALSE.  
  // ************************************  
  
  HANDLE hQueue = NULL;  
  
  hr = MQOpenQueue(  
                   wszFormatName,  
                   MQ_RECEIVE_ACCESS,  
                   MQ_DENY_RECEIVE_SHARE,  
                   &hQueue  
                   );  
  if (FAILED(hr))  
  {  
    return hr;  
  }  
  
  while (SUCCEEDED(hr))  
  {  
    hr = MQReceiveMessage(  
                          hQueue,  
                          1000,  
                          MQ_ACTION_RECEIVE,  
                          &MsgProps,  
                          NULL,                // lpOverlapped  
                          NULL,                // fnReceiveCallback  
                          NULL,                // hCursor  
                          MQ_NO_TRANSACTION    // pTransaction  
                          );  
  
  //  
  // Process the message and returned error codes.  
  //  
  }  
  
  // Close the queue.  
  hr = MQCloseQueue(hQueue);  
  
  return hr;  
}