Reading Messages in a Dead Letter Queue

Reading messages in a dead letter queue is typically a three-function operation: a call to MQGetMachineProperties to retrieve the local computer identifier (its machine GUID), a call to MQOpenQueue to open the queue with receive access, and a call to MQReceiveMessage to read the message.

    To read a message in a dead letter queue
  1. Define an MQQMProps structure that includes PROPID_QM_MACHINE_ID.
    MQQMPROPS QMProps;
    MQPROPVARIANT Variant;
    MSGPROPID PropId;
    GUID    guidMachineId;
        
    PropId = PROPID_QM_MACHINE_ID;                 //PropId
    Variant.vt = VT_CLSID;                         //Type
    Variant.puuid = &guidMachineId;                //Value
        
    QMProps.cProp = 1;                //Number of properties.
    QMProps.aPropID = &PropId;        //Id of property.
    QMProps.aPropVar = &Variant;      //Value of property.
    QMProps.aStatus  = NULL;          //No Error report.
     
  2. Call MQGetMachineProperties to retrieve the machine identifier (PROPID_QM_MACHINE_ID) of the local computer.
    hr = MQGetMachineProperties(
            NULL,
            NULL,
            &QMProps    
            );
    if (FAILED(hr))
     
  3. Translate the machine GUID into a string.
    WCHAR wszMachineGuid[40];
    TBYTE* pszUuid = 0;
    if(UuidToString(&guidMachineId, &pszUuid) != RPC_S_OK)
    {
      //  Handle failure
    }
    else
    {
        wcscpy( wszMachineGuid, pszUuid );
        RpcStringFree(&pszUuid);
    }
     
  4. Prepare the format name of the dead letter queue.
    wsprintf( wszFormatNameBuffer,
              L"MACHINE=%s%s",
              wszMachineGuid,
              L";DEADLETTER"
              );
     
  5. Call MQOpenQueue and open the queue with receive access.
    QUEUEHANDLE hQueue;
        
    hr = MQOpenQueue(
        wszFormatNameBuffer,
        MQ_RECEIVE_ACCESS,
        0,
        &hQueue
        );
    if (FAILED(hr))
     
  6. Define an MQMSGPROPS structure for the message properties to be retrieved.
    MQMSGPROPS MsgProps;
    MQPROPVARIANT aVariant[10];
    MSGPROPID aPropId[10];
    DWORD PropIdCount = 0;
        
    // Prepare property array (PROPVARIANT).
    #define MSG_BODY_LEN    500
    unsigned char ucMsgBody[MSG_BODY_LEN];
    DWORD dwAppspecificIndex;
        
    // Set the PROPID_M_BODY property.
    aPropId[PropIdCount] = PROPID_M_BODY;                 //PropId
    aVariant[PropIdCount].vt = VT_VECTOR|VT_UI1;          //Type
    aVariant[PropIdCount].caub.cElems = MSG_BODY_LEN;     //Value
    aVariant[PropIdCount].caub.pElems = ucMsgBody;
       
    PropIdCount++;
        
    // Set the MQMSGPROPS structure
    MsgProps.cProp = PropIdCount;       //Number of properties.
    MsgProps.aPropID = aPropId;         //Ids of properties.
    MsgProps.aPropVar = aVariant;       //Values of properties.
    MsgProps.aStatus  = NULL;           //No Error report.
     
     
  7. Call MQReceiveMessage and retrieve the messages in the queue. The following call retrieves the first message in the queue.
    hr = MQReceiveMessage(
         hQueue,               // handle to the Queue.
         5 * 60 * 1000,        // Max time (msec) to wait for message.
         MQ_ACTION_RECEIVE,    // Action.
         &MsgProps,            // properties to retrieve.
        NULL,                  // No overlapped structure.
        NULL,                  // No callback function.
        NULL,                  // NO cursor.
        NULL                   // No transaction
        );
    if (FAILED(hr))
     

Example

The following example opens a dead letter queue and retrieves the message body of the first message in the queue.

HRESULT hr;
#define FORMAT_NAME_LEN 80
WCHAR wszFormatNameBuffer[ FORMAT_NAME_LEN];
 
//////////////////////////////////
//  Define an MQQMPROPS structure 
//  for PROPID_QM_MACHINE_ID.
//////////////////////////////////

MQQMPROPS QMProps;
MQPROPVARIANT Variant;
MSGPROPID PropId;
GUID    guidMachineId;

// Set the PROPID_QM_MACHINE_ID property.
PropId = PROPID_QM_MACHINE_ID;                 //PropId
Variant.vt = VT_CLSID;                         //Type
Variant.puuid = &guidMachineId;                //Value

// Set the MQQMPROPS structure
QMProps.cProp = 1;                //Number of properties.
QMProps.aPropID = &PropId;        //Id of properties.
QMProps.aPropVar = &Variant;      //Value of properties.
QMProps.aStatus  = NULL;          //No Error report.


/////////////////////////////////////
//  Retrieving the identifier of the 
//  local computer (machine GUID).
//////////////////////////////////////
hr = MQGetMachineProperties(
       NULL,
       NULL,
       &QMProps 
       );
if (FAILED(hr))
{
    //
    //  Handle failure
    //
}


///////////////////////////////////
//  Translating the machine GUID
//  into a string
//////////////////////////////////
WCHAR wszMachineGuid[40];
WBYTE* pszUuid = 0;
if(UuidToString(&guidMachineId, &pszUuid) != RPC_S_OK)
{
    //
    //  Handle failure
    //
}
else
{
    wcscpy( wszMachineGuid, pszUuid );
    RpcStringFree(&pszUuid);
}


////////////////////////////////
//  Preparing the format name of
//  the dead letter queue.
///////////////////////////////
wsprintf( wszFormatNameBuffer,
          L"MACHINE=%s%s",
          wszMachineGuid,
          L";DEADLETTER"
          );


//////////////////////////////
//  Open the queue for receive
//////////////////////////////

QUEUEHANDLE hQueue;

hr = MQOpenQueue(
    wszFormatNameBuffer,
    MQ_RECEIVE_ACCESS,
    0,
    &hQueue
    );
if (FAILED(hr))
{
    //
    //  Handle failure
    //
}

//////////////////////////////////
//  Define an MQMSGPROPS structure 
//  for the message properties to 
//  be retrieved.
//////////////////////////////////

MQMSGPROPS MsgProps;
MQPROPVARIANT aVariant[10];
MSGPROPID aPropId[10];
DWORD PropIdCount = 0;

// Prepare property array (PROPVARIANT).
#define MSG_BODY_LEN    500
unsigned char ucMsgBody[MSG_BODY_LEN];
DWORD dwAppspecificIndex;

// Set the PROPID_M_BODY property.
aPropId[PropIdCount] = PROPID_M_BODY;                 //PropId
aVariant[PropIdCount].vt = VT_VECTOR|VT_UI1;          //Type
aVariant[PropIdCount].caub.cElems = MSG_BODY_LEN;     //Value
aVariant[PropIdCount].caub.pElems = ucMsgBody;

PropIdCount++;

// Set the MQMSGPROPS structure
MsgProps.cProp = PropIdCount;       //Number of properties.
MsgProps.aPropID = aPropId;         //Ids of properties.
MsgProps.aPropVar = aVariant;       //Values of properties.
MsgProps.aStatus  = NULL;           //No Error report.


/////////////////////////////////////
// Read first message in dead 
// letter queue.
/////////////////////////////////////

hr = MQReceiveMessage(
 hQueue,               // handle to the Queue.
     5 * 60 * 1000,        // Max time (msec) to wait for message.
     MQ_ACTION_RECEIVE,    // Action.
     &MsgProps,            // properties to retrieve.
    NULL,                  // No overlapped structure.
    NULL,                  // No callback function.
    NULL,                  // NO cursor.
    NULL                   // No transaction
    );
if (FAILED(hr))
{
//
//  Handle failure
//
}