【问题标题】:Cannot determine whether a queue with the specified format name exists无法确定是否存在具有指定格式名称的队列
【发布时间】:2010-12-27 06:12:01
【问题描述】:

执行以下代码时出现异常。有什么想法有什么问题吗?

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

编辑: 这是异常消息和堆栈跟踪的第一行

无法判断是否有指定格式名的队列 存在。
在 System.Messaging.MessageQueue.Exists(字符串路径)

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

【问题讨论】:

  • 请提供异常信息

标签: c# exception msmq


【解决方案1】:

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

Exists 不能被调用来验证 存在远程专用队列。

尝试这样做会产生InvalidOperationException


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

This post from the excellent "MSMQ from the plumber's mate" blog 建议另一种选择:甚至不检查您的队列是否存在,“而是在发现队列不存在时处理未传递的消息。” (您需要跟踪管理队列和/或死信队列,但无论如何您可能都应该这样做。)

【讨论】:

    【解决方案2】:

    试试这个...

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

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

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

    【讨论】:

    【解决方案3】:

    上面检查异常消息的答案确实适用于引发英语异常的系统。我的系统引发了荷兰例外。我得到“De time-out voor de gevraagde bewerking is verstreken”。所以这不是一个非常健壮的解决方案异常有一个属性 MessageQueueErrorCode 应该用于检查是否发生了 IOTimeout。

    所以最好用

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

    代替:

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

    【讨论】:

      【解决方案4】:

      您不能在远程队列上使用 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;
                  }
              }
      

      【讨论】:

        【解决方案5】:

        我最终得到了来自 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;
                }
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-20
          • 2013-10-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多