C# 如何读取另一台机器上的MSMQ计数?

C# 如何读取另一台机器上的MSMQ计数?,c#,.net,msmq,performancecounter,message-queue,C#,.net,Msmq,Performancecounter,Message Queue,我的程序正在成功地使用.NET的MessageQueue类从MSMQ读取。队列是用户可配置的,有时在本地计算机上,有时在远程计算机上。用户可以通过名称或IP地址以及队列名称(我只使用“专用”队列)指定远程计算机 我想向用户显示队列中还有多少消息,但还没有找到方法。MessageQueue类似乎没有一个Count(或类似的)属性来轻松地将其提供给我 我已经能够使用PerformanceCounter和PerformanceCounterCategory类来获取计数-但这似乎只在本地计算机上对我有效

我的程序正在成功地使用.NET的MessageQueue类从MSMQ读取。队列是用户可配置的,有时在本地计算机上,有时在远程计算机上。用户可以通过名称或IP地址以及队列名称(我只使用“专用”队列)指定远程计算机

我想向用户显示队列中还有多少消息,但还没有找到方法。MessageQueue类似乎没有一个Count(或类似的)属性来轻松地将其提供给我

我已经能够使用PerformanceCounter和PerformanceCounterCategory类来获取计数-但这似乎只在本地计算机上对我有效(尽管我不能完全确定我是否正确使用了这些类)


我的问题是如何从远程机器上的MSMQ读取计数(邮件数)?

这可能是您的解决方案:

这可能是您的解决方案:

这可能有些过分,但您可能会将WCF服务放在承载队列的同一台机器上,因此,您可以使用WCF服务中的性能计数器检索计数,并通过该服务的方法公开该功能。

这可能有些过分,但您可以将WCF服务放在承载队列的同一台机器上,因此,您可以使用WCF服务中的性能计数器检索计数,并通过该服务的方法公开该功能。

我想在这里说几句话

  • 在我得到自己的答案之前,我想评论一下约翰·奥普恩卡尔的解决方案(在威利博士的学徒回答中)。他的代码在远程机器上运行。我在工作中的项目中使用了他的代码来观察远程集群服务器上的队列,它运行得非常好

  • 因此,如果出现“RemoteMachineNotAvailable”错误,请检查您的配置。是否所有机器都在同一网络中,或者(不要忘记)队列在远程机器上的安全权限是否设置为允许其他人读取? 用户/帐户是否有足够的权限从其他系统读取

例如,我们必须允许集群队列中的所有人

  • 据我所知,PerformanceCounter在读取远程机器上的消息属性时确实存在问题。我曾尝试在Windows Server群集环境中将它们用于队列,但始终无法使其正常工作。当时我做了一些互联网研究,但不幸的是,我不记得这是出于安全原因还是仅仅是一个bug-(

  • 现在是实际答案。如果您不喜欢John Opincar描述的游标方法,您也可以使用or方法

我从未尝试过GetMessageEnumerator,但我可以说我不推荐GetAllMessages()

当我们在一个包含数千条消息的多个队列的系统上每秒使用它时,我们遇到了严重的性能问题。 该方法获取队列中所有消息的快照,这可能会导致内存和网络负载过大

游标方法仍然有点慢。但是,至少在我们的生产环境中,它比GetAllMessages()解决方案感觉更敏捷

如果在您的场景中计算消息的频率不需要达到1秒,而且您要计算的消息比我们要少,那么使用GetAllMessages()或GetMessageEnumerator()可能是一种可行的解决方案


最后,它总是归结到你自己的个人需要。

我想在这里说几句话

  • 在我得到自己的答案之前,我想评论一下John Opncar的解决方案(在Wily博士的学徒回答中)。他的代码在远程机器上工作。我在我们的工作项目中使用了他的代码来观察远程集群服务器上的队列,它工作得非常好

  • 因此,如果出现“RemoteMachineNotAvailable”错误,请检查您的配置。是否所有机器都在同一网络中?或者-不要忘记-队列在远程机器上的安全权限是否设置为允许其他人读取? 用户/帐户是否有足够的权限从其他系统读取

例如,我们必须允许集群队列中的所有人

  • 据我所知,PerformanceCounters在读取远程计算机上的消息属性时确实存在问题。我曾尝试在Windows Server群集环境中将它们用于队列,但始终无法使其正常工作。当时我做了一些internet研究,但不幸的是,我不记得这是出于安全原因还是simp这是一只虫子-(

  • 现在是实际答案。如果您不喜欢John Opincar描述的游标方法,您也可以使用or方法

我从未尝试过GetMessageEnumerator,但我可以说我不推荐GetAllMessages()

当我们在一个包含数千条消息的多个队列的系统上每秒使用它时,我们遇到了严重的性能问题。 该方法获取队列中所有消息的快照,这可能会导致内存和网络负载过大

游标方法仍然有点慢。但是,至少在我们的生产环境中,它比GetAllMessages()解决方案感觉更敏捷

如果在您的场景中计算消息的频率不需要达到1秒,而且您要计算的消息比我们要少,那么使用GetAllMessages()或GetMessageEnumerator()可能是一种可行的解决方案


最后,它总是取决于您自己的需要。

获取本地队列中消息计数的最可靠解决方案是使用p/Invoke.Ther使用MSMQ API
        var machineName = "mymachine01";
        var formatName = "FormatName:DIRECT=OS:mymachine01\private$\ftpreceived":
        try
        {
            var msmqManagement = new MSMQ.MSMQManagement();
            msmqManagement.Init(machineName, null, formatName );
            return (uint)msmqManagement.MessageCount;
        }
        catch (COMException ex)
        {
            // If queue is not active or does not exist.
            if (ex.ErrorCode == -1072824316)
            {
                return 0;
            }

            throw;
        }
            var query = String.Format("select MessagesinQueue from Win32_PerfRawdata_MSMQ_MSMQQueue where name ='{0}'", path.Replace("\\", "\\\\"));
        var selectQuery = new SelectQuery(query);
        using (var searcher = new ManagementObjectSearcher(selectQuery))
        using (var results = searcher.Get())
        {
            foreach (var result in results)
            {
                var messages = result["MessagesinQueue"].ToString();
                return long.Parse(messages);
            }
        }