Есть ли способ проверить, сколько сообщений в очереди MSMQ? - PullRequest
37 голосов
/ 06 октября 2010

Мне было интересно, есть ли способ программно проверить, сколько сообщений в частном или общедоступном MSMQ, используя C #?У меня есть код, который проверяет, пуста ли очередь или нет, используя метод peek, завернутый в try / catch, но я никогда не видел ничего о показе количества сообщений в очереди.Это было бы очень полезно для мониторинга, если резервное копирование очереди выполняется.

Ответы [ 9 ]

34 голосов
/ 30 октября 2012

Вы можете прочитать значение счетчика производительности для очереди непосредственно из .NET:

using System.Diagnostics;

// ...
var queueCounter = new PerformanceCounter(
    "MSMQ Queue", 
    "Messages in Queue", 
    @"machinename\private$\testqueue2");

Console.WriteLine( "Queue contains {0} messages", 
    queueCounter.NextValue().ToString());
22 голосов
/ 18 апреля 2014

API недоступен, но вы можете использовать GetMessageEnumerator2, что достаточно быстро. Пример:

MessageQueue q = new MessageQueue(...);
int count = q.Count();

Осуществление

public static class MsmqEx
{
    public static int Count(this MessageQueue queue)
    {
        int count = 0;
        var enumerator = queue.GetMessageEnumerator2();
        while (enumerator.MoveNext())
            count++;

        return count;
    }
}

Я также пробовал другие варианты, но у каждого есть свои недостатки

  1. Счетчик производительности может сгенерировать исключение "Экземпляр" ... "не существует в указанной категории."
  2. Чтение всех сообщений с последующим подсчетом выполняется очень медленно, оно также удаляет сообщения из очереди
  3. Кажется, проблема в методе Peek, который вызывает исключение
7 голосов
/ 11 декабря 2015

Если вам нужен быстрый метод (25 000 вызовов в секунду на моем устройстве), я рекомендую версию Ayende, основанную на MQMgmtGetInfo () и PROPID_MGMT_QUEUE_MESSAGE_COUNT:

для C # https://github.com/hibernating-rhinos/rhino-esb/blob/master/Rhino.ServiceBus/Msmq/MsmqExtensions.cs

для VBhttps://gist.github.com/Lercher/5e1af6a2ba193b38be29

Вероятно, происхождение было http://functionalflow.co.uk/blog/2008/08/27/counting-the-number-of-messages-in-a-message-queue-in/, но я не уверен, что эта реализация 2008 года больше работает.

4 голосов
/ 06 октября 2010

Мы используем MSMQ Interop. В зависимости от ваших потребностей вы можете упростить это:

    public int? CountQueue(MessageQueue queue, bool isPrivate)
    {
        int? Result = null;
        try
        {
            //MSMQ.MSMQManagement mgmt = new MSMQ.MSMQManagement();
            var mgmt = new MSMQ.MSMQManagementClass();
            try
            {
                String host = queue.MachineName;
                Object hostObject = (Object)host;
                String pathName = (isPrivate) ? queue.FormatName : null;
                Object pathNameObject = (Object)pathName;
                String formatName = (isPrivate) ? null : queue.Path;
                Object formatNameObject = (Object)formatName;
                mgmt.Init(ref hostObject, ref formatNameObject, ref pathNameObject);
                Result = mgmt.MessageCount;
            }
            finally
            {
                mgmt = null;
            }
        }
        catch (Exception exc)
        {
            if (!exc.Message.Equals("Exception from HRESULT: 0xC00E0004", StringComparison.InvariantCultureIgnoreCase))
            {
                if (log.IsErrorEnabled) { log.Error("Error in CountQueue(). Queue was [" + queue.MachineName + "\\" + queue.QueueName + "]", exc); }
            }
            Result = null;
        }
        return Result;

    }
3 голосов
/ 17 июня 2014
            //here queue is msmq queue which you have to find count.        
            int index = 0;
            MSMQManagement msmq = new MSMQManagement() ;   
            object machine = queue.MachineName;
            object path = null;
            object formate=queue.FormatName;
            msmq.Init(ref machine, ref path,ref formate);
            long count = msmq.MessageCount();

Это быстрее, чем вы выбрали. Вы получаете ссылку на класс MSMQManagement внутри "C: \ Program Files (x86) \ Microsoft SDKs \ Windows", просто просматривая этот адрес, вы получите его. для более подробной информации вы можете посетить http://msdn.microsoft.com/en-us/library/ms711378%28VS.85%29.aspx.

1 голос
/ 12 июня 2017

У меня была реальная проблема с получением принятого ответа из-за ошибки xxx does not exist in the specified Category.Ни одно из приведенных выше решений не помогло мне.

Тем не менее, простое указание имени машины, как показано ниже, может исправить это.

private long GetQueueCount()
{
    try
    {
        var queueCounter = new PerformanceCounter("MSMQ Queue", "Messages in Queue", @"machineName\private$\stream")
        {
            MachineName = "machineName"
        };

        return (long)queueCounter.NextValue();
    }
    catch (Exception e)
    {
        return 0;
    }
}
0 голосов
/ 02 ноября 2016

Количество сообщений в очереди можно найти с помощью следующего кода.

MessageQueue messageQueue = new MessageQueue(".\\private$\\TestQueue");
var noOFMessages = messageQueue.GetAllMessages().LongCount();
0 голосов
/ 31 июля 2014

Это сработало для меня. Использование Enumarator, чтобы сначала убедиться, что очередь пуста.

   Dim qMsg As Message ' instance of the message to be picked 
        Dim privateQ As New MessageQueue(svrName & "\Private$\" & svrQName) 'variable svrnme = server name ; svrQName = Server Queue Name
        privateQ.Formatter = New XmlMessageFormatter(New Type() {GetType(String)}) 'Formating the message to be readable the body tyep
        Dim t As MessageEnumerator 'declared a enumarater to enable to count the queue
        t = privateQ.GetMessageEnumerator2() 'counts the queues 

        If t.MoveNext() = True Then 'check whether the queue is empty before reading message. otherwise it will wait forever 
            qMsg = privateQ.Receive
            Return qMsg.Body.ToString
        End If
0 голосов
/ 09 октября 2010

Самый быстрый метод, который я нашел для получения счетчика очередей сообщений, - это использовать метод peek со следующего сайта :

protected Message PeekWithoutTimeout(MessageQueue q, Cursor cursor, PeekAction action)
{
  Message ret = null;
  try
  {
     ret = q.Peek(new TimeSpan(1), cursor, action);
  }
  catch (MessageQueueException mqe)
  {
     if (!mqe.Message.ToLower().Contains("timeout"))
     {
        throw;
     }
  }
  return ret;
}

protected int GetMessageCount(MessageQueue q)
{
  int count = 0;
  Cursor cursor = q.CreateCursor();

  Message m = PeekWithoutTimeout(q, cursor, PeekAction.Current);
  {
     count = 1;
     while ((m = PeekWithoutTimeout(q, cursor, PeekAction.Next)) != null)
     {
        count++;
     }
  }
return count;
}
...