C-C++ Code Example: Sending a Message Using a COM+ 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
Message Queuing provides a way to use the context that is associated with the current COM+ object to send messages within a COM+ transaction. The COM+ context can then be used to either commit or abort a transaction that includes send operations.
Note
As in all send transactions, messages are not actually sent until the transaction commits, and the destination queue must be transactional.
When your application calls MQSendMessage with a request to send a message within a COM+ transaction (with the pTransaction parameter set to MQ_MTS_TRANSACTION, which is the default), Message Queuing verifies that your application is running in the context of a COM+ transaction. If Message Queuing finds that no COM+ object is running or that the current COM+ object is not executing in a transaction, the message is sent as a nontransactional message. To avoid an attempt to send a nontransactional message to a transactional queue, which will fail, your application can call IsInTransaction to verify that the current COM+ object is executing in a transaction before the message is sent.
If the current context is not transactional, your application can explicitly or implicitly create its own transaction for the message. In the following example, a single-message transaction is used if the current COM+ object is not participating in a transaction.
Note
Several of the functions and methods noted in the following procedure are provided by both MTS (Microsoft® Transaction Server) and COM+ (Component Services). When writing applications for computers running Microsoft® Windows NT® 4.0, Windows® 98, or Windows 95, use the functions and methods provided by MTS. When writing applications for computers running Microsoft Windows® 2000 or later, use the functions and methods provided by COM+ (Component Services).
To send a message within a COM+ transaction
Call GetObjectContext to get the context that is associated with the current COM+ object.
Note
The GetObjectContext function is provided by MTS or COM+ (Component Services), depending on which operating system you are running.
Call IsInTransaction to verify that the current COM+ object is executing in a transaction.
Note
The IsInTransaction method is provided by MTS or COM+, depending on which operating system you are running.
Set the pTransaction variable to MTS_TRANSACTION or MQ_SINGLE_MESSAGE, depending on the return value of IsInTransaction.
Call MQSendMessage to send the message.
Call SetAbort or SetComplete to abort or commit the transaction.
Note
The SetAbort and SetComplete methods are provided by MTS or COM+ (Component Services), depending on which operating system you are running.
Code Example
The following example shows how to get the context of the current COM+ object, check the transactional status of the current COM+ object, set the pTransaction parameter, and then send a message.
Note
This example uses functions and methods provided by COM+ (Component Services). This code will only work on computers running Microsoft Windows 2000 or later.
#include <comsvcs.h> // Specifies COM+ methods and functions
#include <mq.h>
HRESULT hr = MQ_OK;
// Get the context associated with the current COM+ object.
IObjectContext *pContext = NULL;
hr = GetObjectContext (&pContext);
if (FAILED (hr))
{
fprintf(stderr, "GetObjectContext failed. Error: 0x%x\n",hr);
}
// Specify the type of transaction. Use MQ_MTS_TRANSACTION if the
// current COM+ context is transactional. Use MQ_SINGLE_MESSAGE
// if current COM+ context is not transactional.
ITransaction *pTransaction;
pTransaction = MQ_MTS_TRANSACTION;
if (!pContext->IsInTransaction())
{
pTransaction = MQ_SINGLE_MESSAGE;
}
// Send the message.
hr = MQSendMessage(
hQueue,
&MsgProps,
pTransaction
);
if (FAILED (hr))
{
fprintf(stderr, "MQOSendMessage failed.. Error: 0x%x\n",hr);
pContext->SetAbort();
}
else
{
pContext->SetComplete();
}
pContext->Release();