The MQReceiveMessage function allows you to read messages in the queue or subqueue. When reading messages, you can either peek at (not removing them) or retrieve the messages (removing them) in the queue.
Messages can be read either synchronously, asynchronously, or through a transaction.
HRESULT APIENTRY MQReceiveMessage( QUEUEHANDLE hSource, DWORD dwTimeout, DWORD dwAction, MQMSGPROPS * pMessageProps, LPOVERLAPPED lpOverlapped, PMQRECEIVECALLBACK fnReceiveCallback, HANDLE hCursor, ITransaction * pTransaction );
[in] Handle to the queue that contains the message. For transactions, specify a queue on a local computer.
[in] Time, in milliseconds, to wait for the message. This parameter can be set to INFINITE, 0, or a specific amount of time. The default setting is INFINITE. For more information, see Remarks.
[in] How the message is read in the queue. Specify one of the following:
Reads the message at the current cursor location and removes it from the queue.
Reads the message at the current cursor location but does not remove it from the queue. The cursor remains pointing at the current message.
If a cursor was not created by MQCreateCursor (hCursor is NULL), the queue's cursor can point only to the first message in the queue.
Reads the next message in the queue (skipping the message at the current cursor location) but does not remove it from the queue.
You must call MQCreateCursor (hCursor is not NULL) before you can use MQ_ACTION_PEEK_NEXT.
[in, out] On input, a pointer to an MQMSGPROPS structure that specifies which message properties will be received. This parameter can be set to NULL.
On output, it contains the received message property values.
[in, out] Pointer to an OVERLAPPED structure that can be used in asynchronous receive operations based on a completion port or an event mechanism. Setting this parameter to a valid pointer makes the receive operation asynchronous. Set this parameter to NULL for synchronous receive operations and transactions as well as for asynchronous receive operations that do not employ an OVERLAPPED structure.
[in] Pointer to the callback function. Set this parameter to NULL for synchronous receive operations and transactions as well as for asynchronous receive operations that do not employ a callback function.
[in] Handle to cursor for looking at messages in the queue. This parameter can be set to NULL. See the following Remarks section.
[in] Must be a pointer to a transaction object, a constant, or NULL.
Transaction objects can be obtained internally from Message Queuing (by calling MQBeginTransaction), or externally from Microsoft DTC (Distributed Transaction Coordinator).
Specifies that the call is not part of a transaction.
Instructs Message Queuing to verify that a COM+ object is running and that the current COM+ object is participating in a transaction. If Message Queuing finds that the application is running in the context of a COM+ (Component Services) transaction, the message is retrieved within the current COM+ transaction. Otherwise, the message is retrieved outside of a transaction. For more information, see COM+ Transactions.
Requests a single-message transaction. Note that a request to retrieve a message in a single-message transaction using this constant is equivalent to a request to retrieve a single message from a transactional queue outside of a transaction using MQ_NO_TRANSACTION.
Specifies that the call is part of an externally coordinated, XA-compliant transaction.
NULL indicates the message is not retrieved as part of a transaction.
The action specified in dwAction does not agree with the access mode with which the queue was opened.
The buffer supplied for PROPID_M_BODY, PROPID_M_COMPOUND_MESSAGE, PROPID_M_EXTENSION, or PROPID_M_SOAP_ENVELOPE is too small. Details can be retrieved from the aStatus array. In each case, the portion of the property that fits is copied to the buffer, but the message is not removed from the queue.
Message Queuing was unable to connect to the MS DTC.
The supplied format name buffer is too small to hold the format name of the queue.
MQ_ACTION_PEEK_NEXT cannot be used when the current cursor position is at the end of the queue.
One of the following message properties was specified (in pMessageProps) without its associated length property: PROPID_M_ADMIN_QUEUE, PROPID_M_DEST_QUEUE, PROPID_M_LABEL, PROPID_M_RESP_QUEUE, PROPID_M_XACT_STATUS_QUEUE, or PROPID_M_PROV_NAME.
The queue handle specified in hSource is not valid.
No message was received within the time-out period specified by dwTimeout.
The supplied message label buffer is too small to hold the label of the message.
A message that is currently pointed at by the cursor has been removed from the queue. It can be removed by another process or by another call to MQReceiveMessage using a different cursor, or the message time-to-be-received timer has expired.
The operation was canceled before it could be completed. For example, the queue handle was closed by another thread while waiting for a message.
The supplied provider name buffer is too small to hold the cryptographic service provider's name.
One or more message properties specified in pMessageProps resulted in an error.
The queue was deleted before the message could be read. The specified queue handle is no longer valid and the queue handle must be closed.
The supplied sender certificate buffer is too small to hold the user certificate.
The sender identifier buffer supplied is too small.
The Message Queuing service is not available.
The supplied signature buffer is too small to hold the message's digital signature.
The specified queue handle was obtained in a previous session of the Message Queuing service. Close the queue and open it again to obtain a fresh handle.
The supplied symmetric key buffer is too small to hold the symmetric key.
One of the following actions was attempted within the context of a transaction:
An attempt was made to read a message from a remote queue.
An attempt was made to peek a message inside a transaction.
An attempt was made to read a message from a nontransactional queue.
An attempt was made to read a message using a callback function or an OVERLAPPED structure.
An asynchronous operation is pending.
One or more of the properties specified in pMessageProps resulted in a warning code even though the function is completed.
All message properties can be read. However, only those properties specified in the pMessageProps parameter are returned to the calling application; other properties are simply discarded when the message is read. For example, you might choose to retrieve the size of the message without retrieving the message body itself.
When retrieving a message body, you should always look at the body type of the message before looking at the message body itself. Always retrieve PROPID_M_BODY and PROPID_M_BODY_TYPE together. If you do not check the message body type, assume that the message body is an array of bytes (the Message Queuing COM implementation does this automatically for you). Valid types are listed in the PROPID_M_BODY_TYPE reference topic.
The hCursor parameter contains the handle to a cursor created by MQCreateCursor. Using a cursor is optional and is necessary only when you want to read messages that are not at the front of the queue. When using a cursor, you must peek at the first message in the queue by setting dwAction to MQ_ACTION_PEEK_CURRENT before you make calls with dwAction set to MQ_ACTION_PEEK_NEXT. For more information, see Navigating with Cursors.
To retrieve the message body, you must specify PROPID_M_BODY in pMessageProps. The vt field of the corresponding element in the aPropVar array must be set to VT_UI1 | VT_VECTOR, allowing Message Queuing to use the buffer specified in a CAUB structure to store the message. If the supplied buffer is too small to contain the entire message body, MQReceiveMessage fails and MQ_ERROR_BUFFER_OVERFLOW is returned. The buffer is filled to capacity, and the full message remains in the queue. When this happens, the other properties specified by pMessageProps are still read.
To retrieve the size of the message, specify PROPID_M_BODY_SIZE in pMessageProps. Message Queuing sets PROPID_M_BODY_SIZE to the size of the message body, even if MQReceiveMessage fails because the message body exceeded the buffer allocated by PROPID_M_BODY. When retrieving the message body size, the CAUB structure associated with the PROPID_M_BODY property does not indicate the size. The cElems member of the CAUB structure merely indicates the maximum size of the message body that can be copied into the buffer pointed to by the pElems member. Message Queuing never modifies the cElems member.
Not all properties require the application to specify the property type in the vt field of the aPropVar array. For these properties, the corresponding vt field in the aPropVar array can be set to VT_NULL.
The dwTimeout parameter can be set to the following values:
Processing is blocked in the applicable thread until a message is found in the queue (this is the default setting).
A message is read if one is found, or an MQ_ERROR_IO_TIMEOUT (for synchronous reading) or MQ_INFORMATION_OPERATION_PENDING (for asynchronous reading) error is returned immediately.
A positive amount of time (in milliseconds)
Message Queuing waits for a message for the specified amount of time.
Messages cannot be read from a queue that resides on a remote computer without a direct connection. Opening a queue with receive access or peek access requires a direct connection to the computer where the queue resides, and an RPC session is established during calls to receive or peek at messages. For more information, see Opening Remote Queues with Peek or Receive Access.
If the connection between the local computer (the RPC client) and the remote computer (the RPC server) breaks during a call to MQReceiveMessage, the client RPC service waits two hours (by default) before failing the call. At the same time, Message Queuing on the client cancels the RPC session and fails the call after a time interval equal to the sum of five minutes (by default) and the time specified in the dwTimeout parameter. Thus, you can prevent MQReceiveMessage from blocking execution for two hours by setting the dwTimeout parameter to a short time interval. On the RPC server, RPC waits two hours (by default) after the RPC session fails before initiating the context run-down routine to release the resources allocated on the remote computer. However, if a message arrives at the remote queue during this waiting period, Message Queuing tries to return the message to the client through RPC. At this point, RPC detects the communication failure and initiates the run-down routine at once.
To synchronously read messages, set fnReceiveCallback and lpOverlapped to NULL. When this is done, the calling thread is blocked until a suitable message is available or a time-out occurs. For information about reading messages synchronously, see Synchronous Reading.
When asynchronously reading messages, MQReceiveMessage returns MQ_OK if a suitable message is found. Otherwise, MQReceiveMessage returns immediately with the return value MQ_INFORMATION_OPERATION_PENDING. This return value indicates that the operation is pending and will be completed as soon as a suitable message can be found.
To cancel a pending asynchronous receive call, call CancelIo or MQCloseQueue. The CancelIo function cancels all pending input and output (I/O) operations that were issued by the calling thread. The MQCloseQueue function cancels all input and output (I/O) operations for the given queue handle.
Asynchronous receive is based on standard Microsoft® Win32® mechanisms.
Applications can use a callback function, a Windows® Event mechanism, or a completion port to read messages asynchronously. Callback functions take precedence. If both the fnReceiveCallback and lpOverlapped parameters are passed to MQReceiveMessage, Message Queuing will use the callback routine, and will pass the lpOverlapped pointer to the callback routine.
The output parameters to an asynchronous call to MQReceiveMessage must be kept intact until the operation is complete (that is, you cannot free them or reuse them). Use automatic variables with caution.
When using a callback function, you can register only 63 callbacks at the same time. Internally, Message Queuing uses the WaitForMultipleObjects API, which is limited to 64 objects per process, and one of these is used by the runtime.
Completion ports cannot be used by dependent client applications. On Message Queuing independent clients and servers, queue handles are implemented as Windows NT® file handles, so they can be associated with completion ports. However, on dependent clients, queue handles are not file handles and, as a result, cannot be used with completion ports.
If MQReceiveMessage is called as part of a transaction (pTransaction is not set to MQ_NO_TRANSACTION or NULL), the following parameters must be set accordingly:
The lpOverlapped and fnReceiveCallback parameters must be set to NULL. The receive operation must be synchronous.
The hSource parameter must specify a queue on the local computer.
- dwAction must not specify a peek operation.
Messages cannot be retrieved from remote queues within a transaction.
When the call is made, Message Queuing performs the following tasks.
In the case of a subsequent Abort, the message is returned to its original place in the queue.
In the case of a Commit, a positive acknowledgment message is sent to the sender's administration queue, if acknowledgment messages were requested. The class property of the acknowledgment message is MQMSG_CLASS_ACK_RECEIVE.
Transaction objects cannot be reused after you commit or abort the transaction. If you release the transaction object without calling Commit or Abort, the transaction is aborted for you. For more information, see Message Queuing Transactions.
To peek at or retrieve messages from a local outgoing queue, the corresponding remote destination queue must be opened with administrative access in addition to peek or receive access. Specifically, the handle to the queue (hSource) must be obtained by calling MQOpenQueue with the dwAccess parameter set to MQ_PEEK_ACCESS | MQ_ADMIN_ACCESS or MQ_RECEIVE_ACCESS | MQ_ADMIN_ACCESS. Local administrative permissions are also needed to retrieve messages from an outgoing queue.
When reading acknowledgment messages in an administration queue, you can see if the original message failed to reach its destination or was not retrieved from the queue by looking at the class property (PROPID_M_CLASS) of the acknowledgment message. The class property will contain a positive or negative acknowledgment, depending on the acknowledgment level specified by the original message.
If the class property is positive, the original message body is not included in the acknowledgment message. If the class property is negative, the message body is included as the message body of the acknowledgment message. For a complete description of all the properties of the acknowledgment message, see Acknowledgment Messages.
The receiving application can determine if the sending application expects a response by retrieving the PROPID_M_RESP_QUEUE and PROPID_M_RESP_QUEUE_LEN property when reading a message. PROPID_M_RESP_QUEUE contains the format name of a response queue if a response is requested. For information about how to respond, see Response Messages.
|When opening a response queue to send several response messages, the receiving application can cache the queue handle returned by MQOpenQueue, thus eliminating the need to call MQOpenQueue several times for the same response queue.|
Equivalent COM Method
When using COM components, you can receive messages from a queue by calling the MSMQQueue.Receive and MSMQQueue.ReceiveCurrent methods of the MSMQQueue object, and you can peek at the messages in a queue by calling the MSMQQueue.Peek, MSMQQueue.PeekCurrent, and MSMQQueue.PeekNext methods of the MSMQQueue object.
|For information on||See|
How Message Queuing sets the body type of a message
The following code examples are included in Using Message Queuing.
|For an example of||See|
Reading the first message in a queue synchronously
Reading messages in a queue asynchronously using a completion port
Sending response messages to a response queue
Reading messages using a cursor
Filtering messages based on their application-specific information
Reading messages asynchronously using a callback function
The following sample code shows how to receive or peek at messages from a subqueue.
PCWSTR wszRejectedOrdersQueue =”Direct=OS:mymachine\private$\orders;rejectedorders”; hr = MQReceiveMessage(hQueue, 1000, MQ_ACTION_RECEIVE, &msgprops, NULL, NULL, NULL, MQ_NO_TRANSACTION);
Windows NT/2000/XP: Included in Windows NT 4.0 SP3 and later.
Windows 95/98/Me: Included in Windows 95 and later.
Header: Declared in Mq.h.
Library: Use Mqrt.lib.
ConceptsMessage Queuing Functions