Counting Messages in an MSMQ MessageQueue from C#

Surprisingly, this not as easy as MessageQueue.Count; When I searched for how to do this, I kept seeing solutions that required use of COM interop or Performance Counters. I didn’t really like either of those suggestions so I figured I’d just try Peek with a cursor. I was pleasantly surprised to find that this method was more than adequate for my needs. I ran this against a queue with 1000 (relatively small) messages and, including the time to open the queue, this took only 0.04 seconds. I was using private, transactional queues. I haven’t tested any other scenarios. But for my needs, this worked fine.

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);
	if (m != null)
	{
		count = 1;
		while ((m = PeekWithoutTimeout(q, cursor, PeekAction.Next)) != null)
		{
			count++;
		}
	}
	return count;
}

Enjoy.

14 Responses to “Counting Messages in an MSMQ MessageQueue from C#”

  1. Stuart Clark Says:

    How about you use the MessageQueue.GetAllMessages() method which returns an Message[] then check the size of the array.

    Message[] messages = q.GetAllMessages();
    int count = messages.Count;

  2. jopincar Says:

    Two reasons. First, that will remove the messages from the queue. I just want a count. Second, if the messages were at all large, I would have to put the entire contents of the queue in memeory using this technique.

  3. jopincar Says:

    That last sentence isn’t clear now that I read it (if only you could edit comments). What I meant to say is that if the messages in the queue were large and/or there were a lot of them, I would have to allocate enough memory to hold the all of the messages, which would make getting the count much slower and more RAM intensive than it should be.

  4. ETL Says:

    Most helpful. Thanks!

  5. Tani Says:

    I was also looking for a solution other than COM or Performance Counters. Then, found your post and this is exactly what I was looking for! Thanks a lot!

  6. Tani Says:

    By the way, as you commented above, GetAllMessages() actually does not remove messages from the queue.

  7. Nick Says:

    Cheers, came in handy!

  8. abraham Says:

    The code came in handy. The discussion above was quite useful too.

    Thank you John….& Stuart.

  9. Paul Says:

    Here is another way to do it that may be useful to some. I’m not sure if it has the same overhead that GetAllMEssages() does.

    private int GetMessageCount(MessageQueue q)
    {
    int count = 0;
    System.Messaging.MessageEnumerator me = q.GetMessageEnumerator2();
    while (me.MoveNext(new TimeSpan(0, 0, 0))){
    count++;
    }
    //Cursor cursor = q.CreateCursor();

    return count;
    }

  10. MarkJoel60 Says:

    This was a huge help!

    Works like a charm — thanks…

  11. Man Nguyen Says:

    Awesomely done!

  12. Oliv Says:

    Thanks for you solution. I Prefer to test the property MessageQueueErrorCode of the MessageQueueException than to test if the exception message contains the string “timeout”.

    catch (MessageQueueException messageQueueException)
    {
    if (messageQueueException.MessageQueueErrorCode != MessageQueueErrorCode.IOTimeout)
    {
    throw;
    }
    }

  13. newbieLeo Says:

    woww thank a lot,
    it’s really helpful
    xD

  14. Tim Franklin Says:

    Great! Thanks. I converted it to VB and refactored a bit but it did exactly what I needed.


Leave a Reply