65.9K
CodeProject 正在变化。 阅读更多。
Home

访问传出消息队列 (MSMQ)

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.75/5 (7投票s)

2008年1月11日

CPOL

3分钟阅读

viewsIcon

87999

downloadIcon

1094

一篇描述如何访问发件箱消息队列的文章。

引言

本文描述了如何访问发件箱消息队列,以及如何从发件箱队列中查看和接收消息。

背景

有人要求我开发一个模块,用户可以在其中查看未送达的消息,即那些应该发送给客户端但由于客户端不可用(客户端机器在网络中不可用)而被发送到发件箱队列的消息(这是 Microsoft 消息队列的默认行为)。

起初,我以为这会是一个简单的任务,但在做了一些研究后,我发现它不会像我预想的那么容易。但不知何故,我设法找到了关于如何执行此操作的参考资料。

还有一些事情我仍然无法做到,例如,我仍然无法删除/清除发件箱队列中的消息。我仍然无法获取原始的发件箱队列名称 - 我现在通过选择本地系统中的所有活动队列并过滤掉名称中包含 "private" 的队列来完成此操作,因为发件箱队列始终在其名称中包含 "Direct"。

我承认代码有点粗糙,因为这只是一个快速尝试提交我的第一篇文章。希望它对我的 C# 开发者同伴有所帮助。

form.JPG

compMgmt.JPG

使用代码

本文中的代码基于 COM MSMQ 库。您必须从“添加引用”窗口的“COM”选项卡中添加对 Microsoft Message Queue 3.0 Object 库的引用,如下图所示。

1.JPG

以下代码将返回 ArrayList 中的所有发件箱队列名称。正如我之前所说,我仍然无法获取真正的发件箱队列。在这里,我假设在所有活动队列中,名称中包含“Direct=”的队列是发件箱队列。

此方法使用 MSMQ.MSMQApplication COM 对象来获取所有活动队列的名称; 从这些名称中,我们过滤掉名称中包含 "Direct=" 的队列作为我们所需的队列。 关于 MSMQ.MSMQApplication 类的更多信息,请参阅 此处

private ArrayList GetOutGoingQueueName()
{

    ArrayList OutgoingQueuename = new ArrayList();
    try
    {
        MSMQ.MSMQApplication q = new MSMQ.MSMQApplication();
        object obj = q.ActiveQueues;

        Object[] oArray = (Object[])obj;
        for (int i = 0; i < oArray.Length; i++)
        {
            if (oArray[i] == null)
                continue;

            if (oArray[i].ToString().IndexOf("DIRECT=") >= 0)
            {
                OutgoingQueuename.Add(oArray[i].ToString());
               
            }
        }


    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.ToString());
    }
    return OutgoingQueuename;
        
}

下一个方法将返回队列中的消息总数,当队列名称作为方法参数提供时。

此方法使用 MSMQ.MSMQManagement 对象来初始化队列。 在调用 Init 方法后,对象 mgmt 被转换为 MSMQ.MSMQOutgoingQueueManagement 对象,以获取发件箱消息队列中的消息计数。 关于 MSMQ.MSMQManagementMSMQ.MSMQOutgoingQueueManagement 的更多信息,请分别参阅 此处此处

private int GetMessageCount(string queueName)
{
    int count = 0;
    try
    {

        MSMQ.MSMQManagement mgmt = new MSMQ.MSMQManagement();
        MSMQ.MSMQOutgoingQueueManagement outgoing;
        String s = "YOURPCNAME";
        Object ss = (Object)s;
        String pathName = queueName;
        Object pn = (Object)pathName;
        String format = null;
        Object f = (Object)format;

        mgmt.Init(ref ss , ref f, ref pn);

        outgoing = (MSMQ.MSMQOutgoingQueueManagement)mgmt;
        count = outgoing.MessageCount;
        
    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.ToString());
    }
    return count;
}

第三个方法“ReceiveMessage”将从队列中返回消息,其名称在参数列表中提供。 另一个参数定义要从队列中读取的消息数量。 以下方法使用 MSMQ.MSMQQueueInfo 类读取发件箱队列中的消息。 MSMQQueueInfo 类的 Open 方法需要两个参数。 第一个参数指定应用程序如何访问队列,第二个参数指定谁可以访问队列。 关于这些参数的更多信息,请参阅 此处

Open 方法将返回一个 MSMQ.MSMQQueue 类对象,您可以使用该对象从消息队列接收或查看消息。

关于 MSMQQueueInfoMSMQQueueMSMQMessage 的更多信息,请分别参阅 此处此处此处

private ArrayList ReceiveMessage(string queueFormatName, int numOfMessagesToRead)
{
    ArrayList messages = new ArrayList();
    try
    {
        MSMQ.MSMQQueueInfo info = new MSMQ.MSMQQueueInfo();
        info.FormatName = queueFormatName;
       
        MSMQ.MSMQQueue mq = info.Open((int)(MSMQ.MQACCESS.MQ_ADMIN_ACCESS | 
          MSMQ.MQACCESS.MQ_RECEIVE_ACCESS), (int)MSMQ.MQSHARE.MQ_DENY_NONE);


        object wantdest = false;
        object tr = true;
        object num = 0;

        
        for (int i = 0; i < numOfMessagesToRead; i++)
        {
            MSMQ.MSMQMessage msg = mq.ReceiveCurrent(ref wantdest, 
                                   ref wantdest, ref tr, ref num, ref wantdest);
            if (msg == null)
                continue;

            messages.Add(System.Text.ASCIIEncoding.ASCII.GetString((byte[])msg.Body));
        }
        
    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.ToString());
    }
    return messages;
}

PeekReceive 之间的主要区别在于,Peek 方法仅读取消息,而不将其从队列中删除,而 Receive 方法在读取消息后将其从队列中删除。

private ArrayList PeekMessage(string queueFormatName, int numOfMessagesToRead)
{
    ArrayList messages = new ArrayList();
    try
    {
        for (int i = 0; i < numOfMessagesToRead; i++)
        {
            MSMQ.MSMQQueueInfo info = new MSMQ.MSMQQueueInfo();
            info.FormatName = queueFormatName;
    
            MSMQ.MSMQQueue mq = info.Open((int)(MSMQ.MQACCESS.MQ_ADMIN_ACCESS | 
                MSMQ.MQACCESS.MQ_PEEK_ACCESS), (int)MSMQ.MQSHARE.MQ_DENY_NONE);


            object wantdest = false;
            object tr = true;
            object num = 0;

            MSMQ.MSMQMessage msg = null;
            if (i == 0)
                msg = mq.PeekCurrent(ref wantdest, ref tr, ref num, ref wantdest); 
            else
                msg = mq.PeekNext(ref wantdest, ref tr, ref num, ref wantdest); 

            
            if (msg == null)
                continue;

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(System.Text.ASCIIEncoding.ASCII.GetString((byte[])msg.Body));
            XmlNode NODE =  doc.SelectSingleNode("descendant::string");
            messages.Add(NODE.InnerText);
        }
    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.ToString());
    }
    return messages;
}

历史

  • 2008 年 1 月 11 日 - 文章发布。
  • 2008 年 1 月 15 日 - 首次更新 - PeekMessage() 方法实现已更改,并且文章格式已更改。
© . All rights reserved.