This question is maybe the most frequently asked question in the MSMQ newsgroup… It is not hard to understand why:
– Analyzing queue’s depth is the most common action for monitoring / alert tools
– MSMQ documentation is quite vague about the best way to solve the problem
– There is more than one answer…
There are actually two sources from which the number of message can be fetched:
1. MSMQ Performance counters
2. MSMQ Admin APIs
MSMQ performance counters were part of MSMQ since day 1 (I actually owned this part :-)). Performance counters are easy to approach through WMI interface, and many monitoring tools interface to them anyway. However, when using perf. counters you don’t get the most up-to-date data and they are not always accurate, especially when looking at remote machine.
MSMQ Admin APIs were introduced with NT4 SP6a (so you probably have them…) however a COM interface to them was not supplied until MSMQ 3.0 (WXP or W2003). If you have WinNT or Win2K, you will have to use the C APIs. On the other hand, the results from MSMQ Admin APIs are more current and reliable.
.NET managed code API (System.Messaging) does not support this feature yet.
What to use, is still up to you… However, if you are writing a commercial monitoring tool, where accuracy is important, I would recommend using the Admin APIs.
Code sample – MSMQ performance counters via WMI
The following VBS script lists all the queues in your machine and displays the number of messages in each using performance counters with WMI interface:
Option Explicit
Dim Locator ‘ As New WbemScripting.SWbemLocator
Set Locator = CreateObject("WbemScripting.SWbemLocator")
Dim Service ‘ As SWbemServices
Set Service = Locator.ConnectServer()
Dim Query ‘ As string
Query = "Select * From Win32_PerfRawData_MSMQ_MSMQQueue"
Dim objs ‘ As ISWbemObjectSet
Set objs = Service.ExecQuery(Query)
if objs.Count = 0 Then
WScript.Echo "No queues found"
Else
Dim Object ‘ As ISWbemObject
for each object in objs
WScript.Echo object.MessagesInQueue & " Messages in " & object.Name
next
End if
To test the script, copy it to a file with ".VBS" extension (like NoMsgs.vbs) and run (from command line) "CScript NoMsgs.vbs" . You can also remove the comments and compile the script in Visual Basic.
Code sample – MSMQ Admin APIs in MSMQ 3.0
The following code does the same thing – list all the queues in the computer and the number of messages in each – using the MSMQ 3.0 Admin object.
Option Explicit
Dim MSMQApp ‘ As MsmqApplication
Set MSMQApp = CreateObject("MSMQ.MSMQApplication")
Dim qFormat ‘ As String
For each qFormat in MSMQApp.ActiveQueues
Dim Mgmt ‘ As new MSMQManagement
Set Mgmt = CreateObject("MSMQ.MSMQManagement")
Mgmt.Init ,,qFormat
WScript.Echo CLng(Mgmt.MessageCount) & " Messages in " & qFormat
Next
Again – copy the text to a VBS file and it is ready to run.
Not that the two scripts do not yield the exact same result… Performance counters include MSMQ internal queues (admin_queue$, order_queue$, notify_queue$, and machine queues). In addition, it may include an active queue with 0 messages that was long ago deleted from the list for the Admin APIs. Anyway, both APIs do not give a full list of queues, just the active queues – that is, queues that are either open by an application or have messages in them.
If you run on NT4 or Win2K and still want to use the admin APIs to count the number of messags in a queue,you will have to use C/C++ and download the MSMQ Local Admin API package from http://support.microsoft.com/default.aspx?kbid=242471 . If you need a C sample code that does it (uses admin APIs to get the # of messages in a queue in NT4/W2K) please add a comment to this blog, and I will see what I can do.
Cheers,
Yoel
Hi Yoel,Could you please give me a sample code to count the number of messages in a queue using C# and the .NET environment. I do have MSMQ 3.0 on my machine.Thanks much,John
Hi John, thanks a lot for your comment!I just published a new blog (Mar. 21st) that covers someof the .NET ways to count messages in a queue and I hope you will find it usefull.All the best,Yoel
I have been looking for information on this topic for a while. Thanks for sharing you knowledge!!!
hi john, you can use .GetAllMessages().Length to get the number of message in specific queue. MessageQueue MessageInQueue = new System.Messaging.MessageQueue(PrivateQueues[i].Path); MessageInQueue.GetAllMessages().Length;http://juliusr.freeweb7.com/qxplorer.html
Hi Julius,.GetAllMessages().Length will work, but it will first read all the messages from the queue in order to count them… if you have a production queue with several thousand messages, that can be a huge performance issue.
Pingback: MSMQ – Access statistics from .NET? | DeveloperQuestion.com
I cannot get the MSMQManagement.Init method to work if client and server are not in the same Domain. so INIT method works only if client and server are on same domain?
I tried this script for counting messages in queue on different computer i just aded username and password and it returns error Invalid code class 80041010 source SWbemObjectSet
Dim Locator ‘As New WbemScripting.SWbemLocator
Set Locator = CreateObject(“WbemScripting.SWbemLocator”)
strComputer = “x.x.x.x”
Dim Service ‘As SWbemServices
Set Service = Locator.ConnectServer(strComputer, “root\cimv2”, “x.x.x.x\administrator”, “Pa$$word”)
Dim Query ‘As string
Query = “Select * From Win32_PerfRawData_MSMQ_MSMQQueue”
Dim objs ‘ As ISWbemObjectSet
Set objs = Service.ExecQuery(Query)
if objs.Count = 0 Then
WScript.Echo “No queues found”
Else
Dim Object ‘ As ISWbemObject
for each object in objs
WScript.Echo object.MessagesInQueue & ” Messages in ” & object.Name
next
End if