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

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

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(String path)

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

5 ответов

Решение

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

Невозможно вызвать Exists для проверки существования удаленной частной очереди.

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


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

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

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

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

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

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

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

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

вместо:

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

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