Infosys Microsoft Alliance and Solutions blog

« What's in a class/method name? | Main | SQL Server 2005 SP 2 Released »

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).

1

TrackBack

TrackBack URL for this entry:
http://www.infosysblogs.com/microsoft-mt/mt-tb.fcgi/63

Listed below are links to weblogs that reference MSMQ - Sending messages to remote private queues:

» MSMQ - Envoyer un message à une queue distante from Le blog de Fabien Dehopré
J’ai trouvé un article interessant concernant l’envoi de message sur un queue (MSMQ) distante. Ca faisait une semaine que j’essayais, en vain, de me connecter à une queue sur un des serveurs de développement. En fait, je n’é... [Read More]

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~

Very good really helped..Thanks.

Can you please help me on MSMQ - Recieving messages from remote private queues

Thanks! I've been looking for this info for hours. Just what I needed.

@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

Thanks a bunch! I've been stuck on this for quite a while.

Thanks a lot. I have been looking for this all day long

Can you please help me how to read remote private queues in MSMQ 3.0 installed in workgroup mode in windows 2003

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.

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

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.

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.

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

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.

Actually 'DIRECT' is also case sensitive. (as I found out the hard way). strangely it does'nt seem to matter for local computer.

@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).

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?

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.

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?

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")

How do we enable cross server communication with MSMQ [Public or Private] within the same Domain.

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?

@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.

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.

@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.

@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();
}

}

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.

@Atul, still I am unable to send messages to server. Please help.

@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.

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.

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)?

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.

thanks a lot. the original post solved my problem.

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.

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

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?

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 ?

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.

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.

Hi,
No problem atul.
Thanks for the time.

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?

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.

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)