2009-12-16 7 views
14

Ricevo l'eccezione durante l'esecuzione del seguente codice. Qualche idea, cosa c'è che non va?Impossibile determinare se esiste una coda con il nome del formato specificato

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

Edit: Ecco il messaggio di eccezione e la prima linea di stacktrace

non può determinare se una coda con il nome del formato specificato esiste.
a System.Messaging.MessageQueue.Exists (string path)

Si lavora per una coda locale per la via.

+1

forniscono messaggio di eccezione si prega –

risposta

35

Dal vostro campione, sembra che si sta cercando di verificare se esiste una coda privata remota, ma come la documentazione MessageQueue.Exists dice:

esiste non può essere chiamato per verificare l' esistenza di un privato a distanza coda.

Provare a farlo produrrà un InvalidOperationException.


Se davvero bisogno di questa informazione per il flusso di lavoro, è possibile utilizzare il metodo MessageQueue. GetPrivateQueuesByMachine e iterare i risultati per trovare una corrispondenza. Se lo fai, ti consiglio di leggere Are Remote MSMQ Queues Reliable?, che discute questo approccio in modo approfondito.

This post from the excellent "MSMQ from the plumber's mate" blog suggerisce un'altra alternativa: non controllare nemmeno se le code esistono, "ma gestisci la mancata consegna del messaggio se dovesse risultare che la coda non esiste." (Avrete bisogno di monitorare le code di amministrazione e/o lettera morta le code, ma probabilmente si dovrebbe essere facendo comunque.)

4

Prova questa ...

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

Se la coda non esiste oppure se l'account che esegue l'app non ha diritti sufficienti per raggiungerlo, il messaggio di eccezione lo indica chiaramente.

AND, questo funzionerebbe sia con FormatName che con il solito percorso di coda.

+1

Durante il test, mi è stato sempre il timeout quando la coda era vuota. – NealWalters

+0

@NealWalters controlla la mia risposta combinata: http://stackoverflow.com/a/34633405/1306012 –

2

La risposta sopra con la verifica del messaggio di eccezione funziona su sistemi che generano eccezioni in inglese. Il mio sistema solleva eccezioni olandesi. Ho capito che "De timeout out of gevraagde bewerking è verstoken". Quindi non è una soluzione molto robusta L'eccezione ha una proprietà MessageQueueErrorCode che dovrebbe essere usata per verificare se si è verificato un IOTimeout.

Quindi è meglio usare

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

invece di:

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

Non è possibile utilizzare il metodo esiste in una coda remota, in modo da avere a rappresentare un utente su quella macchina remota:

//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

Ho finito con le risposte da Svix, Erwin van Dijk e Joseph Daigle combinato. Inoltre ho controllato per 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; 
     } 
    }