tags:

views:

105

answers:

4

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.

A: 
John Breakwell
Any sample code for that?
My Other Me
No, not to hand. I'll add it to my to-to list.
John Breakwell
+1  A: 

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;

    }
My Other Me
Thanks, 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.)
Justin
Do you have Interop.MSMQ.dll anywhere on your machine? We have it in our assembly collection.
My Other Me
No I don't have that, nor do I see anywhere to download it online.
Justin
A: 

There was a much more obvious way to do this, I hear it doesn't perform well with thousands of records in the queue but for smaller amounts it seems fine:

public static int GetNumMessagesInQueue(string path)
        {
            var queue = new MessageQueue(path);
            return queue.GetAllMessages().Length;
        }
Justin
That will take forever when you have a few thousand messages in the queue. If you only need to do it once it's OK, but if you want to monitor then I can not warn you enough about how slow this will be.
My Other Me
A: 

The fastest method I have found to retrieve a message queue count is to use the peek method from the following site:

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