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.
April 14, 2008 at 6:27 pm
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;
April 15, 2008 at 6:43 am
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.
March 10, 2011 at 4:31 am
q.GetAllMessages does not remove any messages from the list.
http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.getallmessages.aspx
April 15, 2008 at 6:46 am
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.
June 17, 2008 at 5:48 pm
Most helpful. Thanks!
June 26, 2008 at 5:05 pm
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!
July 2, 2008 at 7:39 pm
By the way, as you commented above, GetAllMessages() actually does not remove messages from the queue.
August 12, 2008 at 5:36 am
Cheers, came in handy!
August 21, 2008 at 12:46 pm
The code came in handy. The discussion above was quite useful too.
Thank you John….& Stuart.
September 3, 2008 at 11:08 pm
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;
}
September 26, 2008 at 8:28 am
This was a huge help!
Works like a charm — thanks…
January 22, 2009 at 5:28 pm
Awesomely done!
March 3, 2009 at 8:51 am
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;
}
}
November 4, 2010 at 1:40 am
+1 to you sure, wanted to post the same comment myself.
October 11, 2016 at 3:28 am
^ Agreed. Checking the message for a specific string is bad. What if the exception thrown is localized (e.g. “time-out” in Dutch, “temps mort” in French, “タイムアウト” in Japanese or “sokuvala” in Zulu for example). And besides localization issues: what if the message was: “something went wrong, the timeout was fine but the queue didn’t exist” or what if the message changed after some (windows) update and wouldn’t contain the word “timeout” anymore (“something went wrong, the action timed out”)?
I am exaggerating ofcourse but all of the above scenario’s are, in maybe a more subtle way, very possible. Checking the message property of an exception should only be a very, very last resort (when the exception doesn’t provide any other useful information like the MessageQueueErrorCode property for example). Most exceptions provide enough information.
April 3, 2009 at 2:24 am
woww thank a lot,
it’s really helpful
xD
August 7, 2009 at 2:38 pm
Great! Thanks. I converted it to VB and refactored a bit but it did exactly what I needed.
April 16, 2010 at 9:17 am
Thanks alot! I tried the original solution first but when doing a lot of counts on several queues sequentially I received a MessageQueueException.InvalidHandle sometimes. With Pauls solution I have not yet received any such exception.
August 9, 2011 at 9:44 pm
Hi Magnus
This is a reply to an old post, but I had trouble finding it online so though i’d post it here in case others want the solution to that problem you mentioned. I had this when working on big queues. The solution is to add a line:
queue.EnableConnectionCache = False
(queue = your MessageQueue object)
This tells MSMQ not to rely on its cache and prevents those exceptions you (and I) got.
October 6, 2010 at 4:56 pm
I discovered this may work for generally static queues, but if you have services using these queues while you count, you run into trouble.
The GetMessageEnumerator2 method appears to work even in a queue that is actively being used by other services. Plus, this method has the added benefit of not returning a Message to you when you don’t care about the messages themselves.
October 6, 2010 at 5:20 pm
Robert, I’ve been using this technique in a high-volume, production scenario since I published this and have not had any problems.
November 9, 2010 at 1:43 pm
Robert is correct, you shouldn’t be using a cursor to count messages, especially where the same service or another service may be receiving/removing messages from the queue. Cursors have restrictions related to messages being removed. Instead you could use GetAllMessages().Length, but the key is you’ll want to use a MessageReadPropertyFilter in order to basically filter out all the data to keep the foot print small.
countFilter = new MessagePropertyFilter();
countFilter.AdministrationQueue = false;
countFilter.ArrivedTime = false;
countFilter.CorrelationId = false;
countFilter.Priority = false;
countFilter.ResponseQueue = false;
countFilter.SentTime = false;
countFilter.Body = false;
countFilter.Label = false;
countFilter.Id = false;
June 28, 2012 at 10:07 am
Hi Adrian,
Can you please provide the full code of how your method works? I’m sorry that I’m not that familiar with coding with MessageQueue. So should I just combine the below code with the snippet you provided above? I don’t understand the correlation between MessageReadPropertyFilter object and GetAllMessages method :-(.
Message[] messages = q.GetAllMessages();
int count = messages.Count;
Thanks!
Angie
July 17, 2012 at 10:40 pm
I’ve actually switched to performance counters to monitor queue sizes since on really large queues, even doing a filtered count has a large performance penalty. I do this in a Try/Catch and if an exception occurs I revert to using the GetAllMessages method. This is roughly the code that I use.
private MessagePropertyFilter _messageCountFilter;
public YourClass()
{
_messageCountFilter= new MessagePropertyFilter();
_messageCountFilter.AdministrationQueue = false;
_messageCountFilter.ArrivedTime = false;
_messageCountFilter.CorrelationId = false;
_messageCountFilter.Priority = false;
_messageCountFilter.ResponseQueue = false;
_messageCountFilter.SentTime = false;
_messageCountFilter.Body = false;
_messageCountFilter.Label = false;
_messageCountFilter.Id = false;
}
public int GetQueueCount(string queueName)
{
//try the performance counters, more efficient
try
{
PerformanceCounter performanceCounter = new PerformanceCounter();
performanceCounter.CategoryName = “MSMQ Queue”;
performanceCounter.CounterName = “Messages in Queue”;
performanceCounter.InstanceName = string.Format(“{0}\\{1}”, Environment.MachineName, queueName);
performanceCounter.MachineName = Environment.MachineName;
CounterSample counterSample = performanceCounter.NextSample();
System.Threading.Thread.Sleep(100);
return (int) CounterSample.Calculate(counterSample, performanceCounter.NextSample());
}
catch (Exception ex)
{
Logger.Debug(ex.Message);
}
//if performance counters failed, then use MSMQ object, less efficient
try
{
MessageQueue messageQueue = new MessageQueue(Environment.MachineName + “\\” + queueName);
messageQueue.MessageReadPropertyFilter = _messageCountFilter;
return messageQueue.GetAllMessages().Length;
}
catch (Exception ex)
{
Logger.Error(ex);
}
return -1;
}
July 30, 2012 at 5:37 pm
Hi Adrian,
Using the filter/GetAllMessages method of counting I occasionally run into:
System.Messaging.MessageQueueException: Message that the cursor is currently pointing to has been removed from the queue by another process or by another call to Receive without the use of this cursor.
This is occurring because I have another service receiving messages from the Queue while the count is happening.
How do you avoid this in your systems?
November 9, 2010 at 1:46 pm
Here’s some detailed information regarding cursors and MSMQ.
http://support.microsoft.com/kb/178516
November 9, 2010 at 1:59 pm
MS should implement a Count method. It shouldn’t take more than one line of code to effeciently determine how many items are queued. The code you posted is hardly intuitive (although it does seem reasonable). Have you used this technique in a high-volume, production situation yet?
FYI — I have two services asynchronously accessing the queue on which I’m using the published code. These queues see 65-100K messages a day with bursts of 50 messages per second.
November 9, 2010 at 2:59 pm
You are correct, it shouldn’t take more than one line of code. That’s why I’m the only person that sees this. My other developers work off my framework class that simplifies a lot of the MSMQ complexities that Microsoft didn’t bother to take the extra small step to really make it a complete and friendly interface.
The production situation I designed/developed processes
about 10 million messages a day with bursts up to 500 messages per queue per server, so yes it’s high volume. It consists of various services inserting and removing for process, routing messages, as well as the monitoring of these queues.
I only ran across your article looking for information regarding a minor performance counter issue that’s been annoying me for a while, but thought I’d share my knowledge.
If you want to test it yourself, simply create a queue, insert 10,000 messages with a large enough Body content (say 4K) and compare the performance. Yes, in a production environment you wouldn’t be inserting 4K messages, it’s simply to illustrate the performance impact of using cursors vs GetAllMessages with a filter.
Using a cursor it takes 370ms, while using the method I posted only takes 162ms. You can test with larger messages or more messages, but the results are pretty much always the same, it takes twice as long or more using the cursors since they duplicate the message, where as with GetAllMessages you can control what is read through the filter, thus eliminating the Body from being read/duplicated.
November 25, 2010 at 1:24 am
This was really a very nice article. Now my problem is I want to access the server from my local machine because the server is not having VS so I have to develop the code in my local machine. The steps which I need to follow are as follows:
1. Open the server.
2. Count the no. of messages in the private queue.
3. Show the count on my application page.
So this way, I can show the real time figures in my app.
Step 2 can be achieved by the above method.
Please assist. Thanks.
August 9, 2011 at 9:57 pm
Jopincar’s code works well and used to be the best method, but you should probably use the enumeration method mentioned by Adrian nowadays, as Microsoft say that otherwise you can have issues with messages that are removed or added to the queue. YMMV however. Really stupid that there is no .Count method.
October 16, 2011 at 8:47 pm
I tried using GetMessageEnumerator2().MoveNext() function.
This is fastest way to counting MSMQ.
December 18, 2011 at 2:22 pm
[…] blog posts suggest iterating over messages (e.g. Counting Messages in an MSMQ MessageQueue from C#) or doing it using WMI. WMI is the best alternative in my opinion and if you want a quick way of […]
January 25, 2012 at 11:46 am
Your code doesn’t work reliably.
Call it multiple times on the same, unchanged queue and each time you call it, the result is 2 smaller than the last time.
January 25, 2012 at 12:06 pm
Marty, this code works fine. I’ve been using it for years.
July 27, 2012 at 3:06 pm
Thanks jopincar. I need to read messages one at a time, without deleting them. While I read, new messages keep coming in the queue in high volume and frequency. Will this approach work then? Is it static similar to GetAllMessages() or is it dynamic similar to GetMessageEnumerator2()? I have been using GetAllMessages() as I would prefer static, but it has been giving problems lately
http://stackoverflow.com/questions/11349050/sporadic-error-while-getting-all-messages-in-windows-messagequeue
Thanks.
July 25, 2013 at 11:52 pm
Hi All,
I am agree with Adrian solution, i just modify it for easy understand
private static int MessageQueueCount(MessageQueue msMq)
{
var messageCountFilter = new MessagePropertyFilter
{
AdministrationQueue = false,
ArrivedTime = false,
CorrelationId = false,
Priority = false,
ResponseQueue = false,
SentTime = false,
Body = false,
Label = false,
Id = false
};
msMq.MessageReadPropertyFilter = messageCountFilter;
return msMq.GetAllMessages().Count();
}
Please let me know, if is there any drawback of using this solution or a better way then this.
July 26, 2013 at 12:01 am
I think developer can also add some more properties to false in filter for faster performance.
because he wants just the count not anything data/information about message.
say msMq.GetAllMessages() if we go with without filtration its return all message with all related data & then count.
but msMq.GetAllMessages() if we go with with maximum filtration then its first filter on server then return data which contain minimum information/data and my next step or target is count.
msMq.GetAllMessages().Count()
so go with filter as much as you can.
please correct me if I am wrong.
April 24, 2014 at 9:12 am
from http://msdn.microsoft.com/en-us/library/system.messaging.messagequeue.getallmessages.aspx
“Because GetAllMessages returns a copy of the messages in the queue at the time the method was called, the array does not reflect new messages that arrive in the queue or messages that are removed from the queue.”
if got 50K of messages in the Queue, this can be very slow.
you can use Yoel Arnon’s
blog : http://yoelarnon.wordpress.com/page/2/
WMI PROVIDER FOR MESSAGE COUNT IN QUEUE
http://yoelarnon.wordpress.com/2008/04/02/the-msmq-wmi-provider/
April 24, 2014 at 9:24 am
If you read through the replies, you’ll see that using the performance counters is an easy way to get the message count. You don’t need a third party library to do this.
June 18, 2014 at 8:08 am
[…] John Opincar: https://jopinblog.wordpress.com/2008/03/12/counting-messages-in-an-msmq-messagequeue-from-c/ […]
August 6, 2014 at 6:14 am
[…] http://www.meadow.se/wordpress/retrieving-the-message-count-is-msmq-queues/comment-page-1/#comment-473136https://jopinblog.wordpress.com/2008/03/12/counting-messages-in-an-msmq-messagequeue-from-c/ […]
October 19, 2014 at 6:59 am
[…] Counting Messages in an MSMQ MessageQueue from C# […]
March 10, 2015 at 7:01 am
Which is the best way?
I don’t want delete messages in the list neither messages lost
another way that I have found by google:
// Set the filter to only retrieve no major attributes or body
MessagePropertyFilter propFilter = new MessagePropertyFilter();
propFilter.ClearAll();
MessageQueue newQueue = new MessageQueue(queuePath, false, true, QueueAccessMode.Peek);
newQueue.MessageReadPropertyFilter = propFilter;
if(newQueue.GetAllMessages().Length > 0)
August 31, 2016 at 2:18 pm
[…] blog posts suggest iterating over messages (e.g. Counting Messages in an MSMQ MessageQueue from C#) or doing it using WMI. WMI is the best alternative in my opinion and if you want a quick way of […]