Je me demandais s'il existe un moyen de vérifier par programme combien de messages sont dans un MSMQ privé ou public en utilisant C #? J'ai du code qui vérifie si une file d'attente est vide ou n'utilise pas la méthode Peek intégrée dans un try/catch, mais je n'ai jamais rien vu sur l'affichage du nombre de messages dans la file d'attente. Cela serait très utile pour surveiller si une file d'attente est sauvegardée.
Vous pouvez lire la valeur du compteur de performances pour la file d'attente directement à partir de .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());
Il n'y a pas d'API disponible, mais vous pouvez utiliser GetMessageEnumerator2
qui est assez rapide. Échantillon:
MessageQueue q = new MessageQueue(...);
int count = q.Count();
La mise en oeuvre
public static class MsmqEx
{
public static int Count(this MessageQueue queue)
{
int count = 0;
var enumerator = queue.GetMessageEnumerator2();
while (enumerator.MoveNext())
count++;
return count;
}
}
J'ai aussi essayé d'autres options, mais chacune a ses inconvénients
Peek
qui lève une exceptionSi vous avez besoin d'une méthode rapide (25 000 appels/seconde sur ma boîte), je vous recommande la version d'Ayende basée sur MQMgmtGetInfo () et PROPID_MGMT_QUEUE_MESSAGE_COUNT:
pour C # https://github.com/hibernating-rhinos/rhino-esb/blob/master/Rhino.ServiceBus/Msmq/MsmqExtensions.cs
pour VB https://Gist.github.com/Lercher/5e1af6a2ba193b38be29
The Origin était probablement http://functionalflow.co.uk/blog/2008/08/27/counting-the-number-of-messages-in-a-message-queue-in/ mais je suis pas convaincu que cette mise en œuvre de 2008 fonctionne plus.
Nous utilisons le MSMQ Interop. En fonction de vos besoins, vous pouvez probablement simplifier ceci:
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;
}
//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’est plus rapide que celui que vous avez sélectionné . Vous obtenez un renvoi de classe MSMQManagement dans "C:\Program Files (x86)\Microsoft SDKs\Windows". Pour plus de détails, visitez http://msdn.Microsoft.com/en-us/library/ms711378%28VS.85%29.aspx .
J'ai eu de la difficulté à obtenir la réponse acceptée en raison de l'erreur xxx does not exist in the specified Category
. Aucune des solutions ci-dessus n'a fonctionné pour moi.
Cependant, il suffit de spécifier le nom de la machine comme indiqué ci-dessous pour le corriger.
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;
}
}
La méthode la plus rapide que j'ai trouvée pour récupérer un nombre de files d'attente de messages consiste à utiliser la méthode peek à partir du 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;
}
Cela a fonctionné pour moi. Utilisation d'un énumérateur pour vous assurer que la file d'attente est vide en premier.
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