
_START_ARTICLE_
Microsoft Message Queuing
_START_PARAGRAPH_
Microsoft Message Queuing或MSMQ微软公司实现的一种消息队列，始于Windows NT 4与Windows 95。Windows Server 2016与Windows 10仍然包含这种组件。1999年起，Microsoft Embedded平台以及Windows CE 3.0也开始支持这一组件。
_START_SECTION_
使用
_START_PARAGRAPH_
C#例子：_NEWLINE_using System;using System.Collections.Generic;using System.Linq;using System.Messaging;using System.Text;using System.Threading.Tasks;namespace Test{_NEWLINE_    public class QueueManger_NEWLINE_    {_NEWLINE_        /// <summary>_NEWLINE_        /// 创建MSMQ队列_NEWLINE_        /// </summary>_NEWLINE_        /// <param name="queuePath">队列路径</param>_NEWLINE_        /// <param name="transactional">是否事务队列</param>_NEWLINE_        public static void Createqueue(string queuePath, bool transactional = false)_NEWLINE_        {_NEWLINE_            try_NEWLINE_            {_NEWLINE_                //判断队列是否存在_NEWLINE_                if (!MessageQueue.Exists(queuePath))_NEWLINE_                {_NEWLINE_                    MessageQueue.Create(queuePath);_NEWLINE_                    Console.WriteLine(queuePath + "已成功创建！");_NEWLINE_                }_NEWLINE_                else_NEWLINE_                {_NEWLINE_                    Console.WriteLine(queuePath + "已经存在！");_NEWLINE_                }_NEWLINE_            }_NEWLINE_            catch (MessageQueueException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_        }_NEWLINE_        /// <summary>_NEWLINE_        /// 删除队列_NEWLINE_        /// </summary>_NEWLINE_        /// <param name="queuePath"></param>_NEWLINE_        public static void Deletequeue(string queuePath)_NEWLINE_        {_NEWLINE_            try_NEWLINE_            {_NEWLINE_                //判断队列是否存在_NEWLINE_                if (MessageQueue.Exists(queuePath))_NEWLINE_                {_NEWLINE_                    MessageQueue.Delete(@".\private$\myQueue");_NEWLINE_                    Console.WriteLine(queuePath + "已删除！");_NEWLINE_                }_NEWLINE_                else_NEWLINE_                {_NEWLINE_                    Console.WriteLine(queuePath + "不存在！");_NEWLINE_                }_NEWLINE_            }_NEWLINE_            catch (MessageQueueException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_        }_NEWLINE_        /// <summary>_NEWLINE_        /// 发送消息_NEWLINE_        /// </summary>_NEWLINE_        /// <typeparam name="T">用户数据类型</typeparam>_NEWLINE_        /// <param name="target">用户数据</param>_NEWLINE_        /// <param name="queuePath">队列名称</param>_NEWLINE_        /// <param name="tran"></param>_NEWLINE_        /// <returns></returns>_NEWLINE_        public static bool SendMessage<T>(T target, string queuePath, MessageQueueTransaction tran = null)_NEWLINE_        {_NEWLINE_            try_NEWLINE_            {_NEWLINE_                //连接到本地的队列_NEWLINE_                MessageQueue myQueue = new MessageQueue(queuePath);_NEWLINE_                System.Messaging.Message myMessage = new System.Messaging.Message();_NEWLINE_                myMessage.Body = target;_NEWLINE_                myMessage.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });_NEWLINE_                //发送消息到队列中_NEWLINE_                if (tran == null)_NEWLINE_                {_NEWLINE_                    myQueue.Send(myMessage);_NEWLINE_                }_NEWLINE_                else_NEWLINE_                {_NEWLINE_                    myQueue.Send(myMessage, tran);_NEWLINE_                }_NEWLINE_                Console.WriteLine("消息已成功发送到"+queuePath + "队列！");_NEWLINE_                return true;_NEWLINE_            }_NEWLINE_            catch (ArgumentException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_                return false;_NEWLINE_            }_NEWLINE_        }_NEWLINE_        /// <summary>_NEWLINE_        /// 接收消息_NEWLINE_        /// </summary>_NEWLINE_        /// <typeparam name="T">用户的数据类型</typeparam>_NEWLINE_        /// <param name="queuePath">消息路径</param>_NEWLINE_        /// <returns>用户填充在消息当中的数据</returns>_NEWLINE_        public static T ReceiveMessage<T>(string queuePath,MessageQueueTransaction tran=null)_NEWLINE_        {_NEWLINE_            //连接到本地队列_NEWLINE_            MessageQueue myQueue = new MessageQueue(queuePath);_NEWLINE_            myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });_NEWLINE_            try_NEWLINE_            {_NEWLINE_                //从队列中接收消息_NEWLINE_                System.Messaging.Message myMessage = tran == null ? myQueue.Receive() : myQueue.Receive(tran);_NEWLINE_                return (T)myMessage.Body; //获取消息的内容_NEWLINE_            }_NEWLINE_            catch (MessageQueueException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_            catch (InvalidCastException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_            return default(T);_NEWLINE_        }_NEWLINE_        /// <summary>_NEWLINE_        /// 采用Peek方法接收消息_NEWLINE_        /// </summary>_NEWLINE_        /// <typeparam name="T">用户数据类型</typeparam>_NEWLINE_        /// <param name="queuePath">队列路径</param>_NEWLINE_        /// <returns>用户数据</returns>_NEWLINE_        public static T ReceiveMessageByPeek<T>(string queuePath)_NEWLINE_        {_NEWLINE_            //连接到本地队列_NEWLINE_            MessageQueue myQueue = new MessageQueue(queuePath);_NEWLINE_            myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });_NEWLINE_            try_NEWLINE_            {_NEWLINE_                //从队列中接收消息_NEWLINE_                System.Messaging.Message myMessage = myQueue.Peek();_NEWLINE_                return (T)myMessage.Body; //获取消息的内容_NEWLINE_            }_NEWLINE_            catch (MessageQueueException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_            catch (InvalidCastException e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_            return default(T);_NEWLINE_        }_NEWLINE_        /// <summary>_NEWLINE_        /// 获取队列中的所有消息_NEWLINE_        /// </summary>_NEWLINE_        /// <typeparam name="T">用户数据类型</typeparam>_NEWLINE_        /// <param name="queuePath">队列路径</param>_NEWLINE_        /// <returns>用户数据集合</returns>_NEWLINE_        public static List<T> GetAllMessage<T>(string queuePath)_NEWLINE_        {_NEWLINE_            MessageQueue myQueue = new MessageQueue(queuePath);_NEWLINE_            myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(T) });_NEWLINE_            try_NEWLINE_            {_NEWLINE_                Message[] msgArr=  myQueue.GetAllMessages();_NEWLINE_                List<T> list=new List<T>();_NEWLINE_                msgArr.ToList().ForEach((o) => _NEWLINE_                {_NEWLINE_                    list.Add((T)o.Body);_NEWLINE_                });_NEWLINE_                return list;_NEWLINE_            }_NEWLINE_            catch(Exception e)_NEWLINE_            {_NEWLINE_                Console.WriteLine(e.Message);_NEWLINE_            }_NEWLINE_            return null;_NEWLINE_        }_NEWLINE_    }}namespace Test{_NEWLINE_    public class Student_NEWLINE_    {_NEWLINE_        /// <summary>_NEWLINE_        /// 年龄_NEWLINE_        /// </summary>_NEWLINE_        public int Age { get; set; }_NEWLINE_        /// <summary>_NEWLINE_        /// 姓名_NEWLINE_        /// </summary>_NEWLINE_        public string Name { get; set; }_NEWLINE_    }}namespace Test{_NEWLINE_    class Program_NEWLINE_    {_NEWLINE_        static void Main(string[] args)_NEWLINE_        {_NEWLINE_            string queuepath = @".\private$\myQueue";_NEWLINE_            //QueueManger.Createqueue(queuepath);_NEWLINE_            //Student stu = new Student() { Name="shaoshun",Age=18};_NEWLINE_            //QueueManger.SendMessage<Student>(stu, queuepath);_NEWLINE_            //Student stu=  QueueManger.ReceiveMessageByPeek<Student>(queuepath);_NEWLINE_            //Student stu = QueueManger.ReceiveMessage<Student>(queuepath);_NEWLINE_            //Console.WriteLine(stu.Name);_NEWLINE__NEWLINE_            QueueManger.Deletequeue(queuepath);_NEWLINE_            QueueManger.Createqueue(queuepath);_NEWLINE_            MessageQueueTransaction tran = new MessageQueueTransaction();_NEWLINE_            tran.Begin();_NEWLINE_            try_NEWLINE_            {_NEWLINE_                Student stu;_NEWLINE_                for (int i = 0; i < 4; i++)_NEWLINE_                {_NEWLINE_                    stu=new Student(){Name="shaoshun"+i,Age=i};_NEWLINE_                    QueueManger.SendMessage<Student>(stu, queuepath, tran);_NEWLINE_                    if (i == 3)_NEWLINE_                    {_NEWLINE_                        throw new Exception();_NEWLINE_                    }_NEWLINE_                }_NEWLINE_                tran.Commit();_NEWLINE_            }_NEWLINE_            catch_NEWLINE_            {_NEWLINE_                tran.Abort();_NEWLINE_            }_NEWLINE_            Console.ReadKey();_NEWLINE_        }_NEWLINE_    }}_NEWLINE_C语言调用Windows API例子：_NEWLINE_#include "windows.h"  #include "mq.h"  #include "tchar.h"  #define BUFLEN = 256 ;  _NEWLINE_  _NEWLINE_HRESULT CreateMSMQQueue(  _NEWLINE_                        LPWSTR wszPathName,   _NEWLINE_                        PSECURITY_DESCRIPTOR pSecurityDescriptor,  _NEWLINE_                        LPWSTR wszOutFormatName,  _NEWLINE_                        DWORD *pdwOutFormatNameLength  _NEWLINE_                        )  _NEWLINE_{  _NEWLINE_  _NEWLINE_  // Define the maximum number of queue properties.  _NEWLINE_  const int NUMBEROFPROPERTIES = 2;  _NEWLINE_  _NEWLINE_  // Define a queue property structure and the structures needed to initialize it.  _NEWLINE_  MQQUEUEPROPS   QueueProps;  _NEWLINE_  MQPROPVARIANT  aQueuePropVar[NUMBEROFPROPERTIES];  _NEWLINE_  QUEUEPROPID    aQueuePropId[NUMBEROFPROPERTIES];  _NEWLINE_  HRESULT        aQueueStatus[NUMBEROFPROPERTIES];  _NEWLINE_  HRESULT        hr = MQ_OK;  _NEWLINE_  _NEWLINE_  // Validate the input parameters.  _NEWLINE_  if (wszPathName == NULL || wszOutFormatName == NULL || pdwOutFormatNameLength == NULL)  _NEWLINE_  {  _NEWLINE_    return MQ_ERROR_INVALID_PARAMETER;  _NEWLINE_  }  _NEWLINE_  _NEWLINE_  // Set queue properties.  _NEWLINE_  DWORD cPropId = 0;  _NEWLINE_  aQueuePropId[cPropId] = PROPID_Q_PATHNAME;  _NEWLINE_  aQueuePropVar[cPropId].vt = VT_LPWSTR;  _NEWLINE_  aQueuePropVar[cPropId].pwszVal = wszPathName;  _NEWLINE_  cPropId++;  _NEWLINE_  _NEWLINE_  WCHAR wszLabel[MQ_MAX_Q_LABEL_LEN] = L"Test Queue";  _NEWLINE_  aQueuePropId[cPropId] = PROPID_Q_LABEL;  _NEWLINE_  aQueuePropVar[cPropId].vt = VT_LPWSTR;  _NEWLINE_  aQueuePropVar[cPropId].pwszVal = wszLabel;  _NEWLINE_  cPropId++;  _NEWLINE_  _NEWLINE_  // Initialize the MQQUEUEPROPS structure.  _NEWLINE_  QueueProps.cProp = cPropId;               // Number of properties  _NEWLINE_  QueueProps.aPropID = aQueuePropId;        // IDs of the queue properties  _NEWLINE_  QueueProps.aPropVar = aQueuePropVar;      // Values of the queue properties  _NEWLINE_  QueueProps.aStatus = aQueueStatus;        // Pointer to the return status  _NEWLINE_  _NEWLINE_  // Call MQCreateQueue to create the queue.  _NEWLINE_  WCHAR wszFormatNameBuffer[BUFLEN];  _NEWLINE_  DWORD dwFormatNameBufferLength = BUFLEN;  _NEWLINE_  hr = MQCreateQueue(pSecurityDescriptor,         // Security descriptor  _NEWLINE_                     &QueueProps,                 // Address of queue property structure  _NEWLINE_                     wszFormatNameBuffer,         // Pointer to format name buffer  _NEWLINE_                     &dwFormatNameBufferLength);  // Pointer to receive the queue's format name length in Unicode characters not bytes.  _NEWLINE_  _NEWLINE_  // Return the format name if the queue is created successfully.  _NEWLINE_  if (hr == MQ_OK || hr == MQ_INFORMATION_PROPERTY)  _NEWLINE_  {  _NEWLINE_    if (*pdwOutFormatNameLength >= dwFormatNameBufferLength)  _NEWLINE_    {  _NEWLINE_      wcsncpy_s(wszOutFormatName, *pdwOutFormatNameLength - 1, wszFormatNameBuffer, _TRUNCATE);  _NEWLINE_      // ************************************  _NEWLINE_      // You must copy wszFormatNameBuffer into the   _NEWLINE_      // wszOutFormatName buffer.  _NEWLINE_      // ************************************  _NEWLINE_      wszOutFormatName[*pdwOutFormatNameLength - 1] = L'\0';  _NEWLINE_      *pdwOutFormatNameLength = dwFormatNameBufferLength;  _NEWLINE_    }  _NEWLINE_    else  _NEWLINE_    {  _NEWLINE_      wprintf(L"The queue was created, but its format name cannot be returned.\n");  _NEWLINE_    }  _NEWLINE_  }  _NEWLINE_  return hr;  _NEWLINE_}