Is there a way to check how many messages are in a MSMQ Queue?

≡放荡痞女 提交于 2019-11-26 09:38:53

问题


I was wondering if there is a way to programmatically check how many messages are in a private or public MSMQ using C#? I have code that checks if a queue is empty or not using the peek method wrapped in a try/catch, but I\'ve never seen anything about showing the number of messages in the queue. This would be very helpful for monitoring if a queue is getting backed up.


回答1:


You can read the Performance Counter value for the queue directly from .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());



回答2:


There is no API available, but you can use GetMessageEnumerator2 which is fast enough. Sample:

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

Implementation

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

        return count;
    }
}

I also tried other options, but each has some downsides

  1. Performance counter may throw exception "Instance '...' does not exist in the specified Category."
  2. Reading all messages and then taking count is really slow, it also removes the messages from queue
  3. There seems to be a problem with Peek method which throws an exception



回答3:


If you need a fast method (25k calls/second on my box), I recommend Ayende's version based on MQMgmtGetInfo() and PROPID_MGMT_QUEUE_MESSAGE_COUNT:

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

for VB https://gist.github.com/Lercher/5e1af6a2ba193b38be29

The origin was probably http://functionalflow.co.uk/blog/2008/08/27/counting-the-number-of-messages-in-a-message-queue-in/ but I'm not convinced that this implementation from 2008 works any more.




回答4:


We use the MSMQ Interop. Depending on your needs you can probably simplify this:

    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;

    }



回答5:


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

This is faster than you selected one. You get MSMQManagement class refferance inside "C:\Program Files (x86)\Microsoft SDKs\Windows" just brows in this address you will get it. for more details you can visit http://msdn.microsoft.com/en-us/library/ms711378%28VS.85%29.aspx.




回答6:


I had real trouble getting the accepted answer working because of the xxx does not exist in the specified Category error. None of the solutions above worked for me.

However, simply specifying the machine name as below seems to fix it.

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



回答7:


The fastest method I have found to retrieve a message queue count is to use the peek method from the following site:

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



回答8:


This worked for me. Using a Enumarator to make sure the queue is empty first.

   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



回答9:


The message count in the queue can be found using the following code.

MessageQueue messageQueue = new MessageQueue(".\\private$\\TestQueue");
var noOFMessages = messageQueue.GetAllMessages().LongCount();


来源:https://stackoverflow.com/questions/3869022/is-there-a-way-to-check-how-many-messages-are-in-a-msmq-queue

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!