C-C++ Code Example: Sending a Message Using an Internal Transaction

 

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 using an internal transaction. A call to MQBeginTransaction creates a Message Queuing internal transaction object, which can be used to send messages to a queue or read messages from a queue. In this example, the transaction object is used to send a single message. This is the least expensive way to send a message within a transaction.

To send a message within an internal transaction

  1. Define the maximum number of properties to be specified and the property counter.

  2. Define an MQMSGPROPS structure.

  3. Specify the message body and the message label and initialize the MQMSGPROPS structure.

  4. Call MQOpenQueue to open the transactional destination queue to send the message.

  5. Call MQBeginTransaction to create the internal transaction object.

  6. Call MQSendMessage to send the message within the internal transaction initiated.

  7. Call MSMQTransaction.Commit using the pointer to the transaction object to commit the transaction.

  8. Release the transaction object and close the queue.

Code Example

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

HRESULT SendInternalTransMsg(  
                             LPCWSTR wszDestFormatName  
                             )  
{  
  
  // Validate the input string.  
  if (wszDestFormatName == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  
  // Define the maximum number of properties and a property counter.  
  const int NUMBEROFPROPERTIES = 5;               // Number of properties  
  DWORD cPropId = 0;                              // Property counter  
  
  //Define an MQMSGPROPS structure.  
  MQMSGPROPS msgprops;  
  MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];  
  PROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];  
  HRESULT aMsgStatus[NUMBEROFPROPERTIES];  
  
  HANDLE hQueue = NULL;                               // Queue handle  
  HRESULT hr = MQ_OK;                                 // Return code  
  HRESULT tmp_hr = MQ_OK;  
  ITransaction *pTransaction;                         // Pointer to transaction object  
  
  // Define the message body.  
  WCHAR wszMessageBody[] = L"Message sent in an internal transaction.";  
  
  // Specify PROPID_M_BODY.  
  aMsgPropId[cPropId] = PROPID_M_BODY;       
  aMsgPropVar[cPropId].vt = VT_VECTOR | VT_UI1;   
  aMsgPropVar[cPropId].caub.pElems = (LPBYTE)wszMessageBody;  
  aMsgPropVar[cPropId].caub.cElems = sizeof(wszMessageBody);  
  cPropId++;  
  
  // Add additional message properties here. When adding   
  // properties, increment cPropId to reflect the total   
  // number of message properties specified.  
  
  aMsgPropId[cPropId] = PROPID_M_LABEL;       
  aMsgPropVar[cPropId].vt = VT_LPWSTR;   
  aMsgPropVar[cPropId].pwszVal = L"Transactional test message.";  
  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 transactional queue to send the message.  
  
  hr = MQOpenQueue(  
                   wszDestFormatName,                // Format name of the queue  
                   MQ_SEND_ACCESS,                    // Access mode  
                   MQ_DENY_NONE,                      // Share mode  
                   &hQueue                            // OUT: Handle to the queue  
                   );  
  
  if (FAILED(hr))  
  {  
    return hr;  
  }  
  
  // Initiate an internal transaction.  
  
  hr = MQBeginTransaction(&pTransaction);  
  
  if (FAILED(hr))  
  {  
    MQCloseQueue(hQueue);  
    return hr;  
  }  
  
  // Send the message to the destination queue within the internal transaction.  
  
  hr = MQSendMessage(  
                     hQueue,  
                     &msgprops,  
                     pTransaction                     // Pointer to the transaction object  
                     );  
  
  if (FAILED(hr))  
  {  
    tmp_hr = hr;  
    pTransaction->Release();  
    MQCloseQueue(hQueue);  
    return tmp_hr;  
  }  
  
  // Commit the transaction.  
  
  hr = pTransaction->Commit(0,0,0);  
  if (FAILED(hr))  
  {  
    pTransaction->Release();  
    MQCloseQueue(hQueue);  
    return hr;  
  }  
  
  // Release the transaction object and close the queue.  
  
  pTransaction->Release();  
  hr = MQCloseQueue(hQueue);  
  
  return hr;  
}