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

 

Updated: July 19, 2016

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 transactional dead-letter queue (DEADXACT) of the local computer, peeking at the PROPID_M_LABEL property and displaying the label of each message in the queue.

This example receives the computer GUID and uses it to generate the machine format name needed to open the transactional 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 transactional 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 a transactional 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 transactional dead-letter queue.

  5. Call MQOpenQueue to open the transactional 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 transactional dead-letter queue and free resources.

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

HRESULT ReadingComputerXactDeadletter(  
                                      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 a message property structure.  
  MQMSGPROPS MsgProps;  
  MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];  
  MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];   
  HRESULT aMsgStatus[NUMBEROFPROPERTIES];  
  
  HRESULT hr = MQ_OK;  
  
  // Specify the message properties.  
  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 computer journal format name.  
  WCHAR wszFormatName[60] = {0};  
  // ************************************  
  // You must concatenate "MACHINE=", wszComputerId, and ";DEADXACT"  
  // into the wszFormatName buffer.  
  // wszFormatName = "MACHINE=" + wszComputerId + ";DEADXACT"  
  // 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;  
}  

Show: