The message format has changed in MSMQ 4.0 so re-test all your applications

For a while now there's been some, at times quite vociferous, discussion between members of Microsoft's MSMQ ninjas about the impact of the latest change in the MSMQ message format. I say "latest" as the data structure has become more complicated with each new operating system release. If you look at the full list of MSMQ message properties here you will see what has been added:

Windows 2000

  • PROPID_M_AUTHENTICATED_EX - Indicates whether the message was authenticated at the request of the sending application and what type of digital signature was used.
  • PROPID_M_FIRST_IN_XACT - Indicates whether the message was the first message in a transaction.
  • PROPID_M_LAST_IN_XACT - Indicates whether the message was the last message in a transaction.
  • PROPID_M_XACTID - Indicates the transaction identifier for the message.

Windows XP and 2003

  • PROPID_M_COMPOUND_MESSAGE - Provides the entire contents of an SRMP message, including the SOAP envelope and the SOAP attachments associated with it.
  • PROPID_M_COMPOUND_MESSAGE_SIZE - Provides the size of the entire contents of an SRMP message, including the SOAP envelope and the SOAP attachments associated with it.
  • PROPID_M_DEST_FORMAT_NAME - Indicates the destination queue or queues to which the message was sent.
  • PROPID_M_DEST_FORMAT_NAME_LEN - Indicates the length (in Unicode characters) of the format name buffer allocated by the receiving application and the length of the format name string returned in PROPID_M_DEST_FORMAT_NAME.
  • PROPID_M_LOOKUPID - Indicates the lookup identifier of the message.
  • PROPID_M_RESP_FORMAT_NAME (supersedes PROPID_M_RESP_QUEUE.) - Specifies the response queues used for returning application-generated response messages.
  • PROPID_M_RESP_FORMAT_NAME_LEN - Indicates the length (in Unicode characters) of the format name buffer allocated by the receiving application and the length of format name string returned in PROPID_M_RESP_FORMAT_NAME.
  • PROPID_M_SOAP_BODY - Specifies application-generated SOAP body elements for inclusion in the SOAP envelope of an SRMP message.
  • PROPID_M_SOAP_ENVELOPE - Provides the SOAP envelope of an SRMP message.
  • PROPID_M_SOAP_ENVELOPE_LEN - Provides the size of the SOAP envelope of an SRMP message.
  • PROPID_M_SOAP_HEADER - Specifies additional application-generated header elements for inclusion in the SOAP envelope of an SRMP message.
  • PROPID_M_VERSION - Specifies the wire format used to send the message.

Windows Vista and 2008

  • PROPID_M_ABORT_COUNT - Indicates the number of times that transactional processing has been aborted on a message since it was placed in its current queue.
  • PROPID_M_MOVE_COUNT - Indicates the number of times that transactional processing has been aborted on a message during its lifetime.
  • PROPID_M_DEADLETTER_QUEUE - Indicates the path name of an application-specific dead letter queue (DLQ).
  • PROPID_M_DEADLETTER_QUEUE_LEN - Indicates the length (in Unicode characters) of the PROPID_M_DEADLETTER_QUEUE property.

Now, considering that the total message size is fixed, you can see that over time there is going to be less and less space available for the payload. We are, though, only talking about losing 10s, maybe 100s, of bytes in some cases on a 4MB message which doesn't seem much to worry about as most implementations don't send such large messages.

For those that do, though, these changes can mean applications are unable to deliver MSMQ messages after an upgrade of the destination machine and this is discussed in a recent KB article:  

936501 A Message Queuing client that is running a version of Windows that is earlier than Windows Vista cannot send a message to a Message Queuing 4.0 server

This only talks about Windows Vista/2008 but the principle is applicable to earlier operating systems and some application vendors have encountered the problem in the past and already allowed for it in their designs.

The difference with MSMQ 4.0 is that the service reports the problem. Earlier versions would just silently reject the delivery which would leave an outgoing queue continually trying to deliver a poison message.

The options are as follows:

  • Code the application to monitor the Dead Letter Queue for a message with a class of MQMSG_CLASS_NACK_MESSAGE_TOO_LARGE
  • Code the application to cap the maximum payload that goes into the message at a known safe level.
  • If recoding is not possible, downgrade the destination machine to an older operating system

Note: the new NACK class does not appear until Windows Vista service pack 1 or Windows Server 2008. Anyone encountering this problem on the current version of Windows Vista (or an older operating system) should use the second or third approaches.

Note: Dead Lettering is turned off by default.