Home Dashboard Directory Help

Accessing MessageQueue.FormatName throws an exception on queues returned by GetPrivateQueuesByMachine(remoteMachine) on a workgroup computer by Jakub Berezanski


 as Fixed Help for as Fixed

Sign in
to vote
Type: Bug
ID: 762194
Opened: 9/11/2012 1:42:04 PM
Access Restriction: Public
User(s) can reproduce this bug


MessageQueue.GetPrivateQueuesByMachineName() returns an array of MessageQueue objects.
When executed on a workgroup computer, passing the name of a remote computer, the returned MessageQueue objects throw an exception when their FormatName property is accessed:

System.Messaging.MessageQueueException (0x80004005): Invalid queue path name.
at System.Messaging.MessageQueue.ResolveFormatNameFromQueuePath(...)
at System.Messaging.MessageQueue.get_FormatName()

This is a regression, because accessing this property worked in .NET 2.0 and 4.0.

When the FormatName property getter is viewed in ILSpy/Reflector, the difference between .NET 4.5 and earlier is obvious. For the case where queue path is in fact a format name, previous versions did a simple substring operation (to strip the FormatName: prefix). In .NET 4.5, the code is more complicated and ultimately calls the native MQPathNameToFormatName API - which does not support remote paths in workgroup mode and returns an error, causing the exception to be thrown.

Note that the code path which results in a call to MQPathNameToFormatName is taken because GetPrivateQueuesByMachineName sets a private field named queuePath. The MessageQueue constructor does not do this, so for queues constructed from a format name by user code this error does not occur.
Sign in to post a comment.
Posted by Microsoft on 9/11/2012 at 1:52 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
Posted by Jakub Berezanski on 9/11/2012 at 2:01 PM
Workaround 2 (ugly, but efficient):

Force the getter of FormatName to use the old code path (substring) by clearing the private queuePath field and restoring it after accessing the FormatName property. Because MessageQueue caches the format name, subsequent accesses will work.

var field = queue.GetType().GetMember("queuePath", MemberTypes.Field, BindingFlags.Instance | BindingFlags.NonPublic).Single() as FieldInfo;
var savedValue = field.GetValue(queue);
field.SetValue(queue, null);
var dummy = queue.FormatName; // trigger caching of format name
field.SetValue(queue, savedValue);

Of course it is dangerous and brittle dabbling in implementation details, but is the only workaround I found without reduction in functionality.
Posted by Jakub Berezanski on 9/11/2012 at 1:52 PM
Workaround 1:

Create new MessageQueue objects based on paths returned by GetPrivateQueuesByMachine:

IEnumerable<MessageQueue> = MessageQueue.GetPrivateQueuesByMachine(remoteMachine)
.Select(mq => new MessageQueue(mq.Path));

This unfortunately breaks the MachineName and QueueName properties - they throw an exception ("The specified format name does not support the requested operation.").