Search code examples
c#message-queuemsmq

Remote MSMQ FormatName Error


I created a private queue on a development server that is transactional and am trying to push a message to it via C#:

using (var scope = new TransactionScope(TransactionScopeOption.Required))
{
    //AppSetting has: FormatName:DIRECT=OS:.\private$\queue_name
    sampleQueue = new MessageQueue(System.Configuration.ConfigurationManager.AppSettings["q"]);

    var msg = new SampleMessage { CreateDate = DateTime.Now, Body = Guid.NewGuid().ToString() };

    var mess = new Message(msg);
    mess.UseDeadLetterQueue = true;
    mess.Recoverable = true;

    sampleQueue.Send(mess, MessageQueueTransactionType.Single);
    scope.Complete();
}

The SampleMessage class just exposes a CreateDate and Body set of properties - completely generic, as this is just a sample.

When running the code in my local environment (Windows 10 Pro), I can put a message in the queue with the above code successfully. Similarly, if I run the same code on the development server (Windows Server 2016), the message shows up as expected.

My issue comes in with trying to put a message from my local system on to the remote queue (changing the . to the FQDN of the server, which has an entry in my HOSTS file), which kicks back The specified format name does not support the requested operation. For example, a direct queue format name cannot be deleted. if I try to access any of the properties from sampleQueue (above - example property would be MachineName), but if I don't access any properties the message just fails to deliver with no indication as to why and no errors thrown. I enabled dead-letter on the message (above), but neither transactional nor non-transactional show any failed messages, so I'm at a loss. I've also tried FormatName:DIRECT=OS, FormatName:DIRECT=TCP and checked all of the capitalization to be sure it's right with no luck. Also, I ensured Disable un-authenticated RPC calls is not checked and the Windows Firewall has been turned off on both machines.

The production environment will not be associated with an Active Directory domain, so this is all workgroup-based MSMQ. Anonymous Logon has been enabled, queue is definitely transactional and since local works, I'm stumped.

Interestingly enough, when I try to send to the remote queue I see where that pops up in Outgoing Queues. I looked at it, see that it shows a state of Connected, has 0 messages, 0 unacknowledged messages and 0 unprocessed messages. The IP it shows under Next Hop(s) is correct, so name resolution is also working.

Any suggestions? I'm trying to avoid requiring developers to create MSMQ queues on their local machines, but right now that's the only option I can see if I can't get this to work.

Update

Based on a comment below, I created a non-transactional queue called test_queue on the remote server and attempted to send a message to it. It arrived at the destination server, but went into Dead-Letter messages, with a class of The destination queue does not exist listed. The queue name in my config file shows FormatName:DIRECT=OS:remote-server-name\private$\test_queue and it's definitely a private queue, so I'm really confused since the queue is definitely there.


Solution

  • Got it! MSMQ will be the death of me, I swear. The remote server is not part of a domain, so to make connecting to the server easier, I created a zone inside my Active Directory instance, e.g. companyname.local and then had an entry in there for devserver.companyname.local pointing to the proper IP.

    When I created the non-transactional queue and was getting the message The destination queue doesn't exist, I came across this article: https://social.msdn.microsoft.com/Forums/en-US/0d02f666-3f45-427e-9dbd-379435160471/the-destination-queue-does-not-exist?forum=msmq. It mentioned looking at the Queues tab of the message inside the Dead-letter queue and I saw the exact FormatName configuration I had setup, e.g. DIRECT=OS:devserver.companyname.local\private$\queue_name, but the properties of the queue showed a name of devserver\private$\queue_name. On a hunch, and because MSMQ is so fickle, I added a quick HOSTS entry for devserver to that IP (so I could circumvent my DNS zone) and sending to both the transactional and non-transactional queue now works!

    I can't believe MSMQ cared that it got to the right server, but the server name couldn't be resolved like that. This server is in a hosted environment, so it can't hit my DNS instance, but changing it to be just the raw server name did the trickl