Не удается определить, существует ли очередь с указанным именем формата

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

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)

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

Ответы

Ответ 1

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

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

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


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

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

Ответ 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

Ответ выше с проверкой сообщения об исключении работает в системах, которые поднимают английские исключения. Моя система поднимает голландские исключения. Я получаю "Тайм-аут для гвардейской веры". Таким образом, это не очень надежные решения. Исключение имеет свойство 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

В итоге я получил ответы от 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;
        }
    }