2009-12-16 16 views
14

執行以下代碼時出現異常。任何想法有什麼不對?無法確定是否存在指定格式名稱的隊列

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

編輯: 這裏是異常消息和堆棧跟蹤

的第一行不能確定與指定的格式名稱 隊列是否存在。
at System.Messaging.MessageQueue.Exists(String path)

它適用於本地隊列。

+1

提供異常消息請 –

回答

35

從你的樣品,它看起來像你想檢查遠程專用隊列是否存在,但隨着MessageQueue.Exists文件說:

已存在不能被稱爲覈實 存在一個遠程專用的隊列。

試圖這樣做會產生一個InvalidOperationException


如果你確實需要這些信息爲您的工作流程,您可以使用MessageQueue. GetPrivateQueuesByMachine方法和迭代結果找到匹配。如果你這樣做,我建議閱讀Are Remote MSMQ Queues Reliable?,它在一定程度上討論了這種方法。

This post from the excellent "MSMQ from the plumber's mate" blog建議另一種選擇:甚至不檢查你的隊列是否存在,「而是應該處理消息未送達,如果隊列不存在。」 (你需要跟蹤管理隊列和/或死信隊列,但你可能應該這樣做,反正。)

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

如果隊列不存在或者如果運行該應用程序的帳戶沒有足夠的權利來訪問它,那麼異常消息清楚地表明瞭這一點。

並且,這可以與FormatName和通常的隊列路徑一起使用。

+1

測試時,我得到了超時,當隊列是空的。 – NealWalters

+0

@NealWalters檢查我的綜合答案:http://stackoverflow.com/a/34633405/1306012 –

2

以上檢查異常消息的答案對於引發英語異常的系統起作用。我的系統提出了荷蘭例外。我得到了「德超時工」。所以它不是一個非常健壯的解決方案。異常有一個屬性MessageQueueErrorCode,應該用來檢查IOTimeout是否發生。

所以最好使用

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

代替:

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

不能使用在遠程隊列中已存在的方法,所以你必須模擬用戶遠程機器上:

//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; 
      } 
     } 
1

我結束了從Svix,Erwin van Dijk和的回答合併。此外,我檢查了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; 
     } 
    }