MSMQ - Sending messages to remote private queues
Recently a friend was facing issues in sending messages to a private msmq queue on a remote machine. I had worked on this about 4-5 years back and I recalled that I was able to work with remote private queues. So I decided to give it a try again.
Following are things that I found.
1. When working with remote queues, the queue name in the format machinename\private$\queuename doesn't work. This results in an "invalid queue path" error.
2. 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. The other friendly representation is converted to the FormatName and then used. When working with remote queues, unless there is an AD to resolve the queue name, the friendly name won't work. Check out documentation for details.
For Eg.
MessageQueue rmQ = new MessageQueue
("FormatName:Direct=OS:machinename\\private$\\queue");
rmQ.Send("sent to regular queue - Atul");
3. 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".
4. In case you want to use the machine's IP address the syntax will be "FormatName:Direct=TCP:ipaddress\\private$\\queuename".
For Eg.
MessageQueue rmQ = new MessageQueue
("FormatName:Direct=TCP:121.0.0.1\\private$\\queue");
rmQ.Send("sent to regular queue - Atul");
5. 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. So in the earlier examples, I was sending message to a non-transactional queue. To send to a transactional queue, the code would be
MessageQueue rmTxnQ = new MessageQueue
("FormatName:Direct=OS:machinename\\private$\\queue");
rmTxnQ.Send("sent to Txn queue - Atul", MessageQueueTransactionType.Single);
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
6. Finally, when you send messages to remote queue, a temporary outgoing queue is created on your own machine. This is used in case the remote queue is unavailable. If you go to the computer Management console (compmgmt.msc), and expand the Services and Applications / Message Queuing / Outgoing Queues, you would see these queues. The right side of the console should show the details including the state (connected or not) and the IP address(es) for the next hop(s).

Comments
Accidently landed here but good to know that infy got blog for MS category.
Gudoos guys..keep sharing..I've subscribed for this feed.
Mahes~
Posted by: Mahesh Kumar R | February 16, 2007 02:05 PM
Very good really helped..Thanks.
Posted by: Anupama K | March 2, 2007 04:45 AM
Can you please help me on MSMQ - Recieving messages from remote private queues
Posted by: Anupama | March 8, 2007 06:58 AM
Thanks! I've been looking for this info for hours. Just what I needed.
Posted by: Lazy-J | March 15, 2007 07:52 PM
@Anupama, the basics remain the same for sending and receving. Instead of MessageQueue.Send, you will have to use the Receive method. Note that when working with Private queues, it is very important that the you get the name right since there is no domain server to help resolve the remote queue names, as happens in case of public queues
Posted by: Atul Gupta | March 26, 2007 09:13 AM
Thanks a bunch! I've been stuck on this for quite a while.
Posted by: Dan | March 28, 2007 03:56 PM
Thanks a lot. I have been looking for this all day long
Posted by: Anup Gokhale | April 10, 2007 01:28 PM
Can you please help me how to read remote private queues in MSMQ 3.0 installed in workgroup mode in windows 2003
Posted by: Harish Kumar | May 10, 2007 04:05 PM
Harish: The reading from remote private queue should work in the opposite manner. I will try this and post an update as soon as I can.
Posted by: Atul Gupta | May 14, 2007 06:16 AM
I have published a new blog on receiving messages from remote private queue. Check it out here - http://infosysblogs.com/microsoft/2007/05/msmq_receiving_messages_from_r.html
Posted by: Atul | May 28, 2007 12:32 PM
In point 5, you mention that if the transactional properties don't match then the message disappears. Is it possible to determine the "Transactional" property of a direct format queue? I'm moving to transactional queues but my queue writers need to be able to write to both types of queue during the conversion. Direct format queues are also required because I've got queues in multiple domains.
BTW, I found your article really useful. I believe it confirms that queue properties are cached in AD and are not readily available when using the direct format.
Posted by: David O'Keeffe | May 30, 2007 02:30 AM
David: The Transactional property works for local queues but doesn't work for remote queues even with direct format names. That means the developers need to be aware of transactional nature of the queue.
This isn't all that bad since transactional or not is a design decision and will be done upfront and hence when it comes to implementation, you would already be aware of how it behaves.
One other round about way could be to deploy web service on the remote machine which can make a local call and check the transactional nature and revert the value and you can invoke these web services remotely.
Posted by: Atul Gupta | May 30, 2007 05:53 AM
Hi,
I am working on MSMQ 3.0 and Win2k3. I have a question. I have a application running on Machine A and receiving queue on machine B. Lets say i have given invalid queue name or invalid machine name, when application sends a message to queue on Machine B, No exception is thrown and no ack is returned in Administrator queue. How to handle this situation. Please explain.
Thanks
Chidige
Posted by: Chidige | May 30, 2007 09:08 AM
Chidige: Unfortunately, catching such errors with Send isn't possible since MSMQ uses local MSMQ infrastructure to pass on the information to the remote queue. If it doesn't finds it, it will think that the computer or the queue is down.
I have found one option that works for me. You can do a Peek to check for message and if the queue doesn't exists, it will throw up an error. Here's a sample code
MessageQueue rmQ = new MessageQueue("FormatName:Direct=OS:SERVER\\private$\\remote1");
try
{
rmQ.Peek(new TimeSpan(0, 0, 1));
//queue exists, so lets send the message
rmQ.Send("sent to regular queue - Atul");
}
catch (MessageQueueException ex)
{
if(ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound)
MessageBox.Show("Sorry.. No queue with that name");
}
The Peek will cause validation of the queue and will throw an exception if queue is not found. Since our intention is to just validate the queue presence, I have kept a 1 sec timeout. Hope this helps.
Posted by: Atul Gupta | May 31, 2007 09:40 AM
Actually 'DIRECT' is also case sensitive. (as I found out the hard way). strangely it does'nt seem to matter for local computer.
Posted by: Abhinav | June 1, 2007 09:18 AM
@Abhinav: Thanks for the udpate. However in the examples mentioned above, I have tried with both DIRECT and Direct and both work for me (and they are for remote computers).
Posted by: Atul Gupta | June 25, 2007 03:59 AM
Great information! I just found out another issue when trying to send message to a remote queue:
The remote queue must at least have "ANONYMOUS LOGON" send message permission in the queue security settings, otherwise no exception will throw, but your message disappears.
And it is strange, even I set Message. AttachSenderId = true, no sender id in message when recieved. Anyone knows why?
Posted by: zane | August 3, 2007 11:28 PM
I stumbled across this site when I encountered an odd error. My .Net 1.1 app could write transactionaly to any private que on my machine but one. What intrigued me about your post was the fact that no exception was thrown and yet no message was on the destination queue nor any dead letter or other junk queue. This appears to be really serious issue. We send thousands of messages an hour in our app, and we cannot afford to loose one. That's why we're using a transactional disk based queueing mechanism. The fact that a call can fail yet give no indication of failure is monumental in any decision to continue using a trusted subsystem. I can always fix what can be tested and identified, but invisible non-errored errors are a bit of a problem. In your case, case sensitivity of the formatname was the problem. In my case, that was not the issue. My format name was correct and the queuename itself was pulled from a system generated list. Deleting the queue and re-adding fixed the issue (the same unchanged program worked fine), but the concern remains. I know that this queue was working a week ago, because I was testing this very app against. Any input from anyone about this anomaly would be greatly appreciated.
Posted by: Matt McGregor | August 13, 2007 02:07 AM
Hi,
i am using msmq for handling notification.i have a question.i have got 4 to 5 application sending messages to message queue server.Each application wants to get acknowledgment for the messages that particular application send(not all acknowledgments).when i am using administration queue all the acknowledgments are sent there.how can each application fetch acknowledgment for its messages?
Posted by: johnson | August 20, 2007 12:59 PM
The code did not work for me, error says- Format name is invalid. I tried using all the formats given in the posting. Finally one seems to woking for me. Here it is:
mq = New System.Messaging.MessageQueue("FormatName:Direct=http://10.56.13.91/msmq/Private$/testQ1")
Posted by: Ritesh | September 18, 2007 08:28 PM
How do we enable cross server communication with MSMQ [Public or Private] within the same Domain.
Posted by: Abrobit Roy | October 11, 2007 08:09 AM
Hi, The code works perfect for the OS and TCP format but I am not able to get the HTTP-version to work. Is there a specific configuration that needs to be done for a remote private queue via HTTP?
Also, if I use the format posted by Ritesh (http://ipaddress/msmq/...) my message disappears. It is not in the outgoing queue and it is not handled in the destination queue. Anyone has an idea what I am missing?
Posted by: Vicky | November 6, 2007 08:52 AM
@Vicky, what OS are you working on? Note that the HTTP feature of MSMQ works on XP and Windows 2003 onwards and requires the MSMQ Http support to be installed.
You may want to check the documentation on Microsoft site - http://www.microsoft.com/windowsserver2003/technologies/msmq/default.mspx. In the Technical Overview section you will find two articles, one for HTTP and one for HTTPS.
Hope that helps.
Posted by: Atul Gupta | November 11, 2007 03:28 AM
I am trying to connect remote machine using MQueue.Path = "FormatName:DIRECT=OS:libxplkvmz6h\\private$\\tmsmq"
I am not getting any error message. I couldn't find message on remote machine too. Please help me.
Posted by: vamsi | November 12, 2007 07:04 PM
@Vamsi, I am assuming that you have already ensured connectivity to the remote machine by doing a ping to that machine.
You may want to check point 5 in my post above to ensure that you are following the right transactional properties also when sending the message to the queue.
Posted by: Atul Gupta | November 13, 2007 06:17 AM
@Atul, I am able to ping the machine to which i am sending message. I have checked my code and i am sending to transaction queue and followed all steps which you have mentioned. Code i have written
public void OffLineGeniusCall()
{
try
{
// MessageQueue MQueue = new MessageQueue("LIBXPL3CW669.aceins.com\\Private$\\HigherPriorityQueue");
// MessageQueue MQueue = new MessageQueue(ConfigurationManager.AppSettings["HigherPriorityQueue"].ToString());
//MessageQueue MQueue = new MessageQueue("libxplkvmz6h\\highpriorityqueue");
MessageQueue MQueue = new MessageQueue();
MQueue.Path = "FormatName:PRIVATE=553dd1a5-cc51-4f73-a96d-1f009abac025";
//MessageQueue MQueue = new MessageQueue(@"FormatName:DIRECT=HTTP://172.20.212.30\private$\higherpriorityqueue");
//MessageQueue MQueue = new MessageQueue(@"FormatName:DIRECT=OS:libxplkvmz6h\Public\highpriorityqueue");
//MessageQueue MQueue = new MessageQueue(@"FormatName:DIRECT=TCP://172.20.212.30\private$\higherpriorityqueue");
// create the message and set the base properties
System.Messaging.Message Msg = new System.Messaging.Message();
//DataRow row = geniusDataSet.OffLineMessage.NewOffLineMessageRow();
//row[0] = "PolicyId";
//row[1] = "PolicyTxnId";
//row[2] = "GeniusFeedType";
//row[3] = "NumberOfFail";
//geniusDataSet.Tables[0].Rows.Add(row);
Msg.Priority = MessagePriority.Normal;
Msg.Recoverable = true;
Msg.Formatter = new System.Messaging.BinaryMessageFormatter();
Msg.Body = "Testing MSMQ";
Msg.AttachSenderId = true;
MQueue.Send(Msg,MessageQueueTransactionType.Single);
MQueue.Close();
Label1.Text = "Message sent.";
}
catch (Exception ex)
{
Label1.Text = ex.Message.ToString();
}
}
Posted by: vamsi | November 13, 2007 12:58 PM
I have webapplication running on server A and MSMQ installed on server B. Can i send message from server A with out having MSMQ installed on it.
Posted by: krishna | November 13, 2007 05:44 PM
@Atul, still I am unable to send messages to server. Please help.
Posted by: vamsi | November 14, 2007 01:28 AM
@Krishna, you will need MSMQ installed on both machines.
@Vamsi, a couple of things
1. Hope there isn't a problem in message creation. Can you try with a simple string message?
2. Looking at the code, I see lot of commented lines and it looks like you are using the following line as queue path
MQueue.Path = "FormatName:PRIVATE=553dd1a5-cc51-4f73-a96d-1f009abac025";
This format works for Public queues but not private queues.
What should work for you is
FormatName:DIRECT=OS:libxplkvmz6h\private$\highpriorityqueue
Note that i have replaced public with private$
3. As an additional check, you may want to view the security properties on the queue to see if the account using which you are sending the message has write access or not. Usually Everyone has write access, but just cross-verify it.
Posted by: Atul Gupta | November 15, 2007 05:38 AM
Atul, Thank you very much for your answer. I tried with FormatName:DIRECT=OS:libxplkvmz6h\private$\highpriorityqueue and it works now. Problem i faced is due to firewall blocking.
Posted by: vamsi | November 15, 2007 11:53 AM
I am using recoverable messages (non transactional). I have 2 questions:
1. If the remote queue is down, will the messages be lost that are sent during remote end being down?
2. Is there any way I can check if recoverable clause was set (without looking at the code just from msmq admin)?
Posted by: Atul | December 5, 2007 06:16 AM
Atul, the purpose of MSMQ is that it should allow handling of messages even when the remote end is down. In such a case, the messages are stored on sending machine in a temporary queue that is dynamically created.
The transactional property is more useful for writing to queue or reading from queue. If some error happens during that time, the message will still be available in the queue (if say trying to read) and you can re-read it.
Posted by: Atul Gupta | December 11, 2007 03:58 AM
thanks a lot. the original post solved my problem.
Posted by: harish | March 7, 2008 06:21 PM
Hi, Hope to get help from you on problem of memory leaking.
We implement a messaging systems. The server receives message from clients and stores it in MSMQ. It then forward the message to another destination. The program of routing message first enable the MSMQ: MQAutoReceive(q2)
MQAutoReceive (MessageQueue objQName, //) {...//
//......
objQName = new MessageQueue(".\\Private$\\" + qNameToPtTo);
objQName.Formatter = new XmlMessageFormatter(new Type[] { typeof(byte[]) });
objQName.ReceiveCompleted += new ReceiveCompletedEventHandler(nameOfHandler);
objQName.UseJournalQueue = useJournal;
objQName.MessageReadPropertyFilter.ArrivedTime = true;
objQName.BeginReceive();
//......}
The handler of completed message receiving like this:
q2ReceiveCompleted(object p_source, ReceiveCompletedEventArgs p_objAsyncResult)
{
//..........
try{
q2 = ((MessageQueue)(p_source));
m2 = q2.EndReceive(p_objAsyncResult.AsyncResult);
if (m2.ArrivedTime.AddSeconds(msgValidity) {
q2.Refresh();
q2.BeginReceive();
return;
}
m2.TimeToReachQueue = new TimeSpan(0, 0, TIME_TO_REACH_Q);
m2.AdministrationQueue = q2AdminQ;
m2.AcknowledgeType = AcknowledgeTypes.FullReachQueue;
m2.UseJournalQueue = true;
//.........................
}
catch {
}
finally {
q2.Refresh();
q2.BeginReceive();
}
We have very serious problem of memory leaking. We dont really comprehend it as the message in queue is removed (EndReceive), but still memory is growing.
Hope to get help from you.
Thank you.
Posted by: Jimmy Chan | April 2, 2008 10:34 AM
Jimmy, it will be difficult to say that the memory leak in the program is happening due to message queue usage only. You may want to use tools like CLR Profiler or Windbg to try and pin point the problem
Posted by: Atul Gupta | April 2, 2008 11:51 AM
Hi Atul, I have one issue. I am accessing queue on remote machine which is domain controller. But there is exception like "A connection with Active Directory cannot be established. Verify that there are sufficient permissions to perform this operation".
Most of the time it works but sometimes, it gives such exception.
If there is permission issue, can u give steps to set the permission in Active Directory to access the public queue.
Can u help me?
Posted by: prashant | April 3, 2008 03:00 PM
Hi, we use NET profiler to trace and obviously it comes from queue message. Moreover, the memory usage increased by time as message sent/received.
Can I ask you a question? What happened to message in temp queue which is created to send to remote machine. They will be deleted/or kept ?
Posted by: JImmy | April 4, 2008 05:36 AM
Jimmy, messages in temp queue that gets create while remote server is down, are fowarded when the remote queue is up again and are deleted from the temp queue.
Posted by: Atul Gupta | April 4, 2008 09:46 AM
Prashant, I am sorry, but I haven't experimented with public queue and AD. You may have to check the MSDN documentation around the same to find out how to set up security.
But if it was a security/permission issue, it should have never worked. I am surprised that it works sometimes and doesn't sometimes.
Posted by: Atul Gupta | April 4, 2008 09:49 AM
Hi,
No problem atul.
Thanks for the time.
Posted by: prashant | April 4, 2008 12:28 PM
I have the following scenario:
CompA is running IIS6 with the web application. There is a file called usersettings.config. In here is the line that tells it where the remote message queue is compB: add key="MessageQueueServerConnectionString value="FormatName:DIRECT=OS:{0}"/>
Both servers are on the domain and using PRIVATE queue. In the web app when initiating the process to send to the remote queue on compB get the message: "Remote computer is not available." Does anybody have any ideas?
Posted by: umesh | April 8, 2008 03:07 PM
Your connection string has a placeholder. How is that being filled? If you do something like MessageQueue.GetPrivateQueuesByMachine(), and the remote machine is down at that time, you will get this error. See my other blog with details on this here.
Posted by: Atul Gupta | April 9, 2008 03:27 AM