web-dev-qa-db-ja.com

MSMQキューにあるメッセージの数を確認する方法はありますか?

C#を使用してプライベートまたはパブリックMSMQにあるメッセージの数をプログラムで確認する方法があるかどうか疑問に思っていましたか?キューが空であるか、try/catchにラップされたpeekメソッドを使用していないかをチェックするコードがありますが、キュー内のメッセージ数を表示することについては見たことがありません。これは、キューがバックアップされているかどうかを監視するのに非常に役立ちます。

38
Justin

キューのパフォーマンスカウンター値は、.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());
34
Gary Wright

利用可能なAPIはありませんが、 GetMessageEnumerator2 これは十分に高速です。サンプル:

MessageQueue q = new MessageQueue(...);
int count = q.Count();

実装

public static class MsmqEx
{
    public static int Count(this MessageQueue queue)
    {
        int count = 0;
        var enumerator = queue.GetMessageEnumerator2();
        while (enumerator.MoveNext())
            count++;

        return count;
    }
}

他のオプションも試しましたが、それぞれにいくつかの欠点があります

  1. パフォーマンスカウンターmaythrow exception "インスタンス '...'は指定されたカテゴリに存在しません。"
  2. すべてのメッセージを読んでからカウントするのは本当に遅いです。また、キューからメッセージを削除します
  3. 例外をスローするPeekメソッドに問題があるようです
22
oleksii

高速な方法(ボックスで毎秒25k回の呼び出し)が必要な場合は、MQMgmtGetInfo()およびPROPID_MGMT_QUEUE_MESSAGE_COUNTに基づくAyendeのバージョンをお勧めします。

c#の場合 https://github.com/hibernating-rhinos/rhino-esb/blob/master/Rhino.ServiceBus/Msmq/MsmqExtensions.cs

for VB https://Gist.github.com/Lercher/5e1af6a2ba193b38be29

起源はおそらく http://functionalflow.co.uk/blog/2008/08/27/counting-the-number-of-messages-in-a-message-queue-in/ ですが2008年以降のこの実装が機能することを確信していません。

8
Zartag

MSMQ Interopを使用します。ニーズに応じて、おそらくこれを単純化できます。

    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;

    }
4
My Other Me
            //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();

これは、選択したものよりも高速です。 「C:\ Program Files(x86)\ Microsoft SDKs\Windows」内のMSMQManagementクラスの参照を取得します。詳細については、 http://msdn.Microsoft.com/en-us/library/ms711378%28VS.85%29.aspx にアクセスしてください。

3
rhatwar007

xxx does not exist in the specified Categoryエラーのため、受け入れられた回答を機能させるのに本当に苦労しました。上記の解決策のどれも私にとってはうまくいきませんでした。

ただし、次のようにマシン名を指定するだけで修正されるようです。

private long GetQueueCount()
{
    try
    {
        var queueCounter = new PerformanceCounter("MSMQ Queue", "Messages in Queue", @"machineName\private$\stream")
        {
            MachineName = "machineName"
        };

        return (long)queueCounter.NextValue();
    }
    catch (Exception e)
    {
        return 0;
    }
}
1
Chris

メッセージキューカウントを取得するために見つけた最速の方法は、次の site からpeekメソッドを使用することです。

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;
}
0
John Hunter

これは私のために働いた。エニュマレーターを使用して、最初にキューが空であることを確認します。

   Dim qMsg As Message ' instance of the message to be picked 
        Dim privateQ As New MessageQueue(svrName & "\Private$\" & svrQName) 'variable svrnme = server name ; svrQName = Server Queue Name
        privateQ.Formatter = New XmlMessageFormatter(New Type() {GetType(String)}) 'Formating the message to be readable the body tyep
        Dim t As MessageEnumerator 'declared a enumarater to enable to count the queue
        t = privateQ.GetMessageEnumerator2() 'counts the queues 

        If t.MoveNext() = True Then 'check whether the queue is empty before reading message. otherwise it will wait forever 
            qMsg = privateQ.Receive
            Return qMsg.Body.ToString
        End If
0
Emmanuel Makaza