无法确定是否存在具有指定格式名称的队列

时间:2009-12-16 14:12:09

标签: c# exception msmq

执行以下代码时出现异常。有什么想法是错的吗?

string queueName = "FormatName:Direct=TCP:1.1.1.1\\Private$\\test";
MessageQueue queue;

if (MessageQueue.Exists(queueName))
     queue = new System.Messaging.MessageQueue(queueName);
else queue = MessageQueue.Create(queueName);

queue.Send(sWriter.ToString());

编辑: 这是异常消息和stacktrace的第一行

  

无法确定具有指定格式名称的队列   存在。
在System.Messaging.MessageQueue.Exists(String path)

顺便说一句,它适用于本地队列。

5 个答案:

答案 0 :(得分:37)

从您的示例中,您似乎正在尝试检查是否存在远程专用队列,但正如MessageQueue.Exists文档所述:

  

无法调用存在来验证   存在远程私人队列。

尝试这样做会产生InvalidOperationException


如果您确实需要工作流程的此信息,可以使用MessageQueue. GetPrivateQueuesByMachine方法并迭代结果以查找匹配项。如果你这样做,我建议你阅读Are Remote MSMQ Queues Reliable?,它会深入讨论这种方法。

This post from the excellent "MSMQ from the plumber's mate" blog提出了另一种选择:甚至不检查你的队列是否存在,“但是如果事实证明队列不存在,则处理未传递的消息。” (您需要跟踪管理队列和/或死信队列,但无论如何您应该这样做。)

答案 1 :(得分:4)

试试这个......

  public static bool IsQueueAvailable(string queueName)
   {
        var queue = new MessageQueue(queueName);
        try
        {
            queue.Peek(new TimeSpan(0, 0, 5));
            return true;
        }
        catch (MessageQueueException ex)
        {
            return ex.Message.StartsWith("Timeout");
        }
    }

如果队列不存在或者运行应用程序的帐户没有足够的权限来访问它,则异常消息会明确说明。

AND,这适用于FormatName和通常的队列路径。

答案 2 :(得分:2)

检查异常消息的上述答案适用于引发英语异常的系统。我的系统引发了荷兰例外。我得到了“de time-out voor de gevraagde bewerking is verstreken。”因此,它不是一个非常强大的解决方案该异常具有一个属性MessageQueueErrorCode,应该用于检查是否发生了IOTimeout。

所以最好使用

return (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout);

而不是:

return ex.Message.StartsWith("Timeout");

答案 3 :(得分:2)

我最终得到了来自SvixErwin van DijkJoseph Daigle的答案。另外,我检查了ArgumentException

    /// <summary>
    /// Checks if a (remote) Microsoft Message Queue is available
    /// </summary>
    /// <param name="queueName">The name of the Message Queue.</param>
    /// <returns>Returns true if the queue is available otherwise false.</returns>
    public static bool IsQueueAvailable(string queueName)
    {
        MessageQueue queue;
        try
        {
            queue = new MessageQueue(queueName);
            queue.Peek(new TimeSpan(0, 0, 5)); // wait max. 5 sec. to recieve first message from queue (reduce if necessary)
            return true;
        }
        catch (Exception ex)
        {
            if(ex is ArgumentException)
            {   // the provided queue name is wrong.
                return false;
            }
            else if (ex is MessageQueueException)
            {   // if message queue exception occurs either the queue is avialable but without entries (check for peek timeout) or the queue does not exist or you don't have access.
                return (((MessageQueueException)ex).MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout);
            }
            // any other error occurred.
            return false;
        }
    }

答案 4 :(得分:0)

您无法在远程队列上使用Exists方法,因此您必须模拟该远程计算机上的用户:

//usings
using System;
using System.Messaging;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;

//Declaring the advapi32.dll
 [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out IntPtr phToken);

private void IterateRemoteMQ()
    {
        IntPtr userToken = IntPtr.Zero;

        bool success = LogonUser(
          "REMOTE_USERNAME", //Username on the remote machine
          ".",  //Domain, if not using AD, Leave it at "."
          "PASSWORD",  //Password for the username on the remote machine
          9, //Means we're using new credentials, otherwise it will try to impersonate a local user
          0,
          out userToken);

        if (!success)
        {
            throw new SecurityException("Logon user failed");
        }
        //Go through each queue to see if yours exists, or do some operation on that queue.
        using (WindowsIdentity.Impersonate(userToken))
        {
            MessageQueue[] Queues = MessageQueue.GetPrivateQueuesByMachine("192.168.1.10");
            foreach (MessageQueue mq in Queues)
            {
                string MSMQ_Name = mq.QueueName;
            }
        }