In my current project I found out it can be very difficult to pinpoint problems when sending messages to a remote MSMQ. Sometimes messages just disappear without any error in the eventlog or in the server log for MSMQ (see Server Manager / Diagnostics / Applications and Services Log / Microsoft / Windows / MSMQ).
This is what I found: First of all, you need MSMQ installed on your BizTalk Server to write to a remote queue. When you send messages to remote queue, a temporary outgoing queue is created on your local BizTalk machine. This is used in case the remote queue is unavailable. If you go to the Computer Management console and expand the Services and Applications / Message Queuing / Outgoing Queues, you would see these queues. The right side of the Computer management console should show the details including the state (connected or not) and the IP address(es) for the next hop(s). If you want to verify that the messages are sent to the outgoing queue, but somehow get lost when they are sent to the remote queue, you can right-click the outgoing queue and select Pause. The messages will now remain in the outgoing queue.
In case messages are not sent to the remote queue, check the following:
When working with remote queues, the queue name in the format machinenameprivate$queuename doesn’t work. This results in an “invalid queue path” error. The queue name has to be mentioned as FormatName:Direct=OS:machinename\private$\queuename.
This is necessary since the queue access is internally done using the format name syntax only. Further to previous point, note that FormatName is case sensitive. If you mention the earlier string as FORMATNAME:Direct=OS:machinename\private$\queuename, it won’t work. Surprisingly, there is no error thrown in this case. “FormatName” part of the string seems to be the only case sensitive part. Others can appear in different case. For eg. You can write “DIRECT”.
Next the transactional properties of the queue instance you create in code should match with that of the queue you are trying to send the message to. As a gotcha, you can’t check the Transactional property of a queue name to check if the remote queue is transactional. The Transaction property only works for local queues. Below is the code I used, which caused the problem because of the use of the Transactional property:
bool transactional = false;
transactional = queue.Transactional;
transactional = false;
Debug.WriteLine(“[MessageService]: MSMQ transactional send”);
Debug.WriteLine(“[MessageService]: MSMQ non-transactional send”);
If the transactional properties don’t match, the message will not be delivered. The surprising part is again, I didn’t get any error, and the message just disappeared.