Is there a way to check how many messages are in a MSMQ Queue?
Solution 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());
Solution 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
- Performance counter may throw exception "Instance '...' does not exist in the specified Category."
- Reading all messages and then taking count is really slow, it also removes the messages from queue
- There seems to be a problem with
Peek
method which throws an exception
Solution 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.
Solution 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;
}
Solution 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.
Justin
Updated on February 15, 2020Comments
-
Justin over 4 years
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.
-
Justin over 13 yearsThanks, but where is the MSMQ.ManagementClass? I read in another post that you have to include a COM library called "MSMQ 3.0" but I don't see this on the Com tab (using .NET 3.5.)
-
My Other Me over 13 yearsDo you have Interop.MSMQ.dll anywhere on your machine? We have it in our assembly collection.
-
Justin over 13 yearsNo I don't have that, nor do I see anywhere to download it online.
-
Justin over 13 yearsSystem.Messaging.MessageQueueException: MQ_ACTION_PEEK_NEXT specified to MQReceiveMessage cannot be used with the current cursor position. at System.Messaging.MessageQueue.ReceiveCurrent(TimeSpan timeout, Int32 action, CursorHandle cursor, MessagePropertyFilter filter, MessageQueueTransaction internalTransaction, MessageQueueTransactionType transactionType) at System.Messaging.MessageQueue.Peek(TimeSpan timeout, Cursor cursor, PeekAction action)
-
Ali Mst about 12 yearsSee this answer on how to add this reference: stackoverflow.com/a/8258952/16241
-
Randy Burden about 12 yearsTried this method and got the following COMException which unfortunately I cannot resolve as this would require an infrastructure change: This operation is not supported for Message Queuing installed in workgroup mode. :(
-
Christian Fredh almost 11 yearsWorks fine for one queue, but for error queue I'm getting "Instance 'machinename\private$\error' does not exist in the specified Category.". Is that because the queue haven't had any items in queue for a while or do I need to write in a special way for error queue?
-
Christian Fredh almost 11 yearsI added a message in the error queue and then the code works fine for that queue as well. I guess you need to catch this exception (InvalidOperationException) and then it's empty. Bad thing is, the queue could also be non-existent if you get this exception.
-
pasx about 10 yearsI have found that a syntax like ".\private$\testqueue2" which is what I get from someQueue.Path will cause an exception. I ended up using someQueue.FormatName and extracting "machinename\private$\testqueue2" from its content. I also found this approach not to be 100 percent reliable when the queue is just being started or retrieved which made me think that I would be better off with an implementation based on the com dll but I hadn't had time to invest in more testing.
-
barrypicker almost 10 yearsWe are using this exact method, and find that the method GetMessageCount is failing because it is peeking while messages are consumed from the queue. By merely adding a 10ms thread.sleep command after count++ this operates much more smoothly but takes a lot longer. I still think there must be a better way to get count that to insistantly peek a million times... (are we there yet, are we there yet, are we there yet - doh)
-
Roger over 9 yearsI am getting 'Category does not exist.' when attempting to instantiate the PerformanceCounter(). Must there be > 0 messages in the queue? Christian, did you find another work around? I cannot guarantee messages being in the queue in my case.
-
Per-Frode Pedersen over 9 yearsThis code will fail if the queue contains 0 messages, because it will try PeekWithoutTimeout with PeekAction.Next even though PeekWithTimeout with PeekAction.Current returned null. Added null check to answer
-
namford almost 9 yearsThis is a C# question, your answer is VB
-
Jon List over 8 yearsIsn't there a race condition here? What happens if stuff is being added/removed while you are enumerating? Or if stuff is added/removed after you have counted? Is there a way to suspend all interaction with the queue while you count?
-
oleksii over 8 yearsThis method seemed to be thread-safe in a sense it reflects dynamic changes to the queue. From doc "For example, the enumerator can automatically access a lower-priority message placed beyond the cursor's current position, but not a higher-priority message inserted before that position.". Personally I was testing it under load during inserts and deletes and didn't have threading issues. Obviously, this will reflect approx. count of messages if your queue is used. If you need to have exact count, you need to get a static snapshot by calling
GetAllMessages
-
meraydin almost 8 yearsDon't look for another answer! Other than @Zartag's answer, any other method is either slow or unreliable (I have tested all of them, believe me!)
-
Jeroen Maes over 7 yearsThe nuget package Rsft.Lib.Msmq.MessageCounter implements this.
-
Kirill Bestemyanov almost 7 yearsIn this case you get all messages from queue. It is too expensive.
-
maracuja-juice over 5 yearsthis is the fastest method of the ones I tested so far
-
maracuja-juice over 5 yearsThis is definitely not the fastest method. Highest Voted answer: 6x times faster. Second Highest Voted Answer: 3x times faster
-
maracuja-juice over 5 yearsSlow is relative @meraydin But yes this is definitely the fastest.
-
maracuja-juice over 5 yearsWhere in the Windows folder exactly? There are 4 direct subfolders and each of the subfolders have more subfolders... What file do I have to search for?
-
maracuja-juice over 5 yearsbut also the one that requires the most (complicated) code
-
maracuja-juice over 5 yearsAlso @JeroenMaes unfortunately when calling the GetCount method of the library I get an exception.. Filed an issue on their repository.
-
Dave over 3 yearsHow can a question this "easy" be so hard to get right? I'm getting huge pauses or "does not exist in the specified category" error. So much for a "quick look at MSMQ" !!