Click here to Skip to main content
15,881,559 members
Articles / Programming Languages / C#

Message Queue Counting Comparisions

Rate me:
Please Sign up or sign in to vote.
4.91/5 (7 votes)
10 May 2013CPOL2 min read 39.6K   446   15   5
Comparing the different methods of counting messages on a MSMQ

Introduction 

Recently I needed to create a means of visually monitoring the number of messages in multiple message queues.  This should of been relatively simple, create a UI to display the result from myMessageQueue.Count(), however the count method does not exist as part of the message queue class.  

Cursor Method

When I searched for a solution most of the comments where using cursors.  This was the method that I initially used but when I had about > 35,000 messages I found the count to be wildly erratic. The more messages you have in your queue the longer this method will take to count.  

For a full description of using cursors with MSMQ have a look on Microsoft http://support.microsoft.com/kb/178516.

C#
private MessageQueue _messageQueue;
private int CountCursor()
{
    _messageQueue = new MessageQueue(".\\private$\\pingpong", QueueAccessMode.Peek);
    int count = 0;
    Cursor cursor = _messageQueue.CreateCursor();
    Message m = CursorPeekWithoutTimeout(cursor, PeekAction.Current);
    if (m != null)
    {
        count = 1;
        while ((m = CursorPeekWithoutTimeout(cursor, PeekAction.Next)) != null)
        {
            count++;
        }
        if (m != null) m.Dispose();
    }
    cursor.Dispose();
    return count;
}
protected Message CursorPeekWithoutTimeout(Cursor cursor, PeekAction action)
{
    Message ret = null;
    try
    {
        ret = _messageQueue.Peek(new TimeSpan(1), cursor, action);
    }
    catch (MessageQueueException mqe)
    {
        if (mqe.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
        {
            throw;
        }
    }
    return ret;
}

GetAllMessages Method

GetAllMessages returns a static copy of the messages in the queue, this is fine for small one off counts. In the real world you could have several hundred thousand large messages in the queue so to reduce the amount of information bought back we need to set up a message filter. The more messages you have in your queue the longer this method will take to count. 

C#
var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var countFilter = new MessagePropertyFilter
                        {
                            AdministrationQueue = false,
                            ArrivedTime = false,
                            CorrelationId = false,
                            Priority = false,
                            ResponseQueue = false,
                            SentTime = false,
                            Body = false,
                            Label = false,
                            Id = false
                        };
_messageQueue.MessageReadPropertyFilter = countFilter;
return _messageQueue.GetAllMessages().Length;

GetEnumerator2 Method

GetEnumerator2 returns a dynamic list of messages in the queue.  The more messages you have in your queue the longer this method will take to count.

C#
var _messageQueue = new MessageQueue(".\\private$\pingpong", QueueAccessMode.Peek);
var x = _messageQueue.GetMessageEnumerator2();
int iCount = 0;
while (x.MoveNext())
{
   iCount++;
}
return iCount;

PowerShell (WMI) Method

This is by fastest method by far taking about 20ms regardless of how may messages there are to count. This is the only method for counting the message queues on other machines that you have access to. 

C#
private int GetPowerShellCount()
{
    return GetPowerShellCount(".\\private$\pingpong", Environment.MachineName, "", "");
}
private  int GetPowerShellCount(string queuePath, string machine,string username, string password)
{
    var path = string.Format(@"\\{0}\root\CIMv2", machine);
    ManagementScope scope;
    if (string.IsNullOrEmpty(username))
    {
            scope = new ManagementScope(path);
    }
    else
    {
        var options = new ConnectionOptions {Username = username, Password = password};
        scope = new ManagementScope(path, options);
    }
    scope.Connect();
    if (queuePath.StartsWith(".\\")) queuePath=queuePath.Replace(".\\",string.Format("{0}\\",machine));
    
    string queryString = String.Format("SELECT * FROM Win32_PerfFormattedData_msmq_MSMQQueue");
    var query = new ObjectQuery(queryString);
    var searcher = new ManagementObjectSearcher(scope, query);
    IEnumerable<int> messageCountEnumerable =
        from ManagementObject queue in searcher.Get()
        select (int)(UInt64)queue.GetPropertyValue("MessagesInQueue");
    //IEnumerable<string> messageCountEnumerable =
    //  from ManagementObject queue in searcher.Get()
    //  select (string)queue.GetPropertyValue("Name");
    var x = messageCountEnumerable.First();
    return x;
}

Testing

I decided to create a test that would count the messages and count the timing for the messages to be counted. To run the tests included in source code you need to create a private MSMQ on your machine, the name of the queue does not matter as the application will use the first private queue that it finds. The test application needs to run as administrator as you will be purging the message queue before the tests start.

Image 1

References 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
SuggestionAdditional way I found in stack overflow.... Pin
IssaharNoam9-Jan-18 23:36
IssaharNoam9-Jan-18 23:36 
Questionhave you tried COM? Pin
tonny00828-Jul-15 23:46
tonny00828-Jul-15 23:46 
QuestionWMI Method Pin
WellerEE5-Feb-13 3:54
WellerEE5-Feb-13 3:54 
AnswerRe: WMI Method Pin
Bruce Bennett10-May-13 11:04
Bruce Bennett10-May-13 11:04 
GeneralNice to know Pin
Espen Harlinn14-Mar-12 22:14
professionalEspen Harlinn14-Mar-12 22:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.