Не удается определить, существует ли очередь с указанным именем формата - PullRequest
15 голосов
/ 16 декабря 2009

Я получаю исключение при выполнении следующего кода. Есть идеи, что не так?

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: Вот сообщение об исключении и первая строка stacktrace

Невозможно определить, находится ли очередь с указанным именем формата существует.
в System.Messaging.MessageQueue.Exists (String path)

Кстати, работает для локальной очереди.

Ответы [ 5 ]

37 голосов
/ 16 декабря 2009

Из вашего примера похоже, что вы пытаетесь проверить, существует ли удаленная частная очередь, но, как сказано в документации MessageQueue.Exists:

Существующие не могут быть вызваны для проверки существование удаленной частной очереди.

Попытка сделать это приведет к InvalidOperationException.


Если вам действительно нужна эта информация для вашего рабочего процесса, вы можете использовать метод MessageQueue. GetPrivateQueuesByMachine и повторять результаты, чтобы найти совпадение. Если вы это сделаете, я рекомендую прочитать Надежны ли удаленные очереди MSMQ? , в котором подробно рассматривается этот подход.

Этот пост из отличного блога "MSMQ от помощника сантехника" предлагает другую альтернативу: даже не проверяйте, существуют ли ваши очереди, но вместо этого обрабатывает недоставку сообщения в случае его обращения что очередь не существует ". (Вам нужно будет отслеживать очереди администрирования и / или очереди недоставленных сообщений, но, вероятно, вам все равно придется это делать.)

4 голосов
/ 07 сентября 2011

Попробуйте это ...

  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, так и с обычным путем к очереди.

2 голосов
/ 06 января 2016

Я получил ответы от Svix , Эрвин ван Дейк и Джозеф Дейгл вместе взятых Дополнительно я проверил на 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;
        }
    }
2 голосов
/ 28 февраля 2013

Ответ выше с проверкой сообщения об исключении работает на системах, которые вызывают исключения на английском языке. Моя система поднимает голландские исключения. Я получаю "De time-out voor de gevraagde bewerking является верстрекен". Так что это не очень надежные решения. Исключение имеет свойство MessageQueueErrorCode, которое следует использовать для проверки того, произошел ли IOTimeout.

Так что лучше использовать

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

вместо:

return ex.Message.StartsWith("Timeout");
0 голосов
/ 14 января 2014

Вы не можете использовать метод 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;
            }
        }
...