Windows message queuing что это

From Wikipedia, the free encyclopedia

Microsoft Message Queuing (MSMQ) is a message queue implementation developed by Microsoft and deployed in its Windows Server operating systems since Windows NT 4 and Windows 95. Windows Server 2016 and Windows 10 also includes this component. In addition to its mainstream server platform support, MSMQ has been incorporated into Microsoft Embedded platforms since 1999 and the release of Windows CE 3.0.[1]

MSMQ is a messaging protocol that allows applications running on separate servers/processes to communicate in a failsafe manner. A queue is a temporary storage location from which messages can be sent and received reliably, as and when conditions permit. This enables communication across networks and between computers, running Windows, which may not always be connected. By contrast, sockets and other network protocols assume that direct connections always exist.

MSMQ has been available to developers on Microsoft platforms since 1997,[2] and has commonly been used in enterprise software built with Visual Studio, both in the native pre-.NET incarnation (version 5 and 6), and in Visual Studio .NET. Microsoft also has incorporated MSMQ in its messaging technology framework, Windows Communication Foundation (WCF). Under WCF, MSMQ can be used for providing secure, reliable transport with a unified programming model compatible with other communications standards.

MSMQ is responsible for reliably delivering messages between applications inside and outside the enterprise. MSMQ ensures reliable delivery by placing messages that fail to reach their intended destination in a queue and then resending them once the destination is reachable. It also supports security and priority based messaging. Dead letter queues can be created for looking at messages which timed out or failed for other reasons.

MSMQ supports both durable and non-durable messaging to make a trade off between performance or consistency by writing messages to disk or only in RAM. Non-durable messaging can only be achieved by sending express messages via non-transactional queues.

MSMQ also supports transactions. It permits multiple operations on multiple queues, with all of the operations wrapped in a single transaction, thus ensuring that either all or none of the operations will take effect. Microsoft Distributed Transaction Coordinator (MSDTC) supports transactional access to MSMQ and other resources to achieve transactional exact once processing.

The following ports are used for Microsoft Message Queuing operations:

  • TCP: 1801
  • RPC: 135, 2101*, 2103*, 2105*
  • UDP: 3527, 1801
  • * These port numbers may be incremented by 11 if the initial choice of RPC port is being used when Message Queuing initializes. Port 135 is queried to discover the 2xxx ports.[3]
  • Version 1.0 (May 1997). Supports Windows 95, Windows NT 4.0 SP3, Windows 98 and Windows Me.
  • Version 2.0, included with Windows 2000.
    • New features include:[4] Support for registering public message queues in Active Directory, 128-bit encryption and digital certificate support, full COM support for message properties (achieving functional parity with the Win32 API function calls, full DNS path name support, improved performance in multi-threaded applications.
  • Version 3.0, included with Windows XP (Professional, not Home Edition) and Windows Server 2003.
    • New features include:[5] Internet Messaging (referencing queues via HTTP, SOAP-formatted messages, MSMQ support for Internet Information Services), queue aliases, multicasting of messages, and additional support for programmatic maintenance and administration of queues and MSMQ itself.
  • Version 4.0, part of Windows Vista and Windows Server 2008.
    • New features include:[6] Subqueues,[7] improved support for «poison messages» (messages which continually fail to be processed correctly by the receiver), and support for transactional receives of messages from a remote queue.
  • Version 5.0, part of Windows 7 and Windows Server 2008 R2.
    • New features include:[8] support for Secure Hash Algorithm 2.0 (SHA2) and all advanced hash algorithms that are supported in Windows 2008 R2; by default, weaker hash algorithms are disabled.
  • Version 6.0, part of Windows 8 and Windows Server 2012.
  • Version 6.3, part of Windows 8.1 and Windows Server 2012 R2.

MSMQ is heavily used in various Windows Platform-based contact center applications which uses this service for internal notifications and services. [citation needed]

  • List of Microsoft Windows components
  • IBM MQ, similar techonolgy by IBM
  • Java Message Service, similar technology on the Java platform
  • Amazon Simple Queue Service, commoditized messaging service provided by Amazon.com for a per-use fee. It allows users to rent access to messaging without having to maintain their own server.
  • RabbitMQ, open source message queue broker that implements a pre-standard version of AMQP.[9]
  1. ^ «Microsoft Windows CE 3.0 Message Queuing Service». Microsoft Developer Network. 29 June 2006. Retrieved 2009-11-25.
  2. ^ InformationWeek News Connects The Business Technology Community. Informationweek.com (2014-02-04). Retrieved on 2014-02-22. Archived April 10, 2008, at the Wayback Machine
  3. ^ TCP ports, UDP ports, and RPC ports that are used by Message Queuing. Support.microsoft.com (2011-09-28). Retrieved on 2014-02-22.
  4. ^ «Cloud Administrator». Azure Cloud Administrator. Dayasagar Roy. Archived from the original on 2018-11-24. Retrieved 2006-08-05.
  5. ^ «Cloud Administrator». Azure. Dayasagar Roy. Archived from the original on 2018-11-24. Retrieved 2006-08-05.
  6. ^ «Cloud Administrator». Azure. Dayasagar Roy. Archived from the original on 2018-11-24. Retrieved 2006-08-05.
  7. ^ Sub-queues in MSMQ 4.0
  8. ^ «Cloud Administrator». Azure. Dayasagar Roy. Retrieved 2006-08-05.
  9. ^ «ISO/IEC 19464:2014 — Information technology — Advanced Message Queuing Protocol (AMQP) v1.0 specification». www.iso.org. Retrieved 2017-11-07.
  • MSDN documentation

Businesses often find themselves stuck with delays between data transfer among several applications. For example, you may find an order processing application slow as the third-party resources involved in it can be unavailable at times. Messaging Architecture & development tool like MSMQ is ideal for these kinds of scenarios.

MSMQ(Microsoft Message Queuing) provides a distributed and decoupled way of sending and receiving messages between applications. MSMQ acts as a queue manager that easily decides when applications should be isolated and work even if other applications they interact with are down or unavailable.

In this article, you will learn how about Microsoft MSMQ in detail.

What is Microsoft MSMQ?

Microsoft Message Queuing is a messaging infrastructure and development technology that allows two or more applications to send messages to each other without having to immediately know the results. Developed for the Windows Operating System, this development tool acts as a queue manager that assists you in sending objects (serialized) to the queue where they will stay until you receive them. MSMQ allows you to interact between remote machines, even over the Internet in a decoupled way. 

Power Your Data Analytics with Hevo

Hevo helps you migrate your data from multiple sources to a single destination, creating a single source of truth. Easily make your data analysis ready for your data visualization.

Hevo helps you with:

  • Seamless Integration: Consolidate data from multiple sources into one destination.
  • Single Source of Truth: Ensure accurate and consistent data for your analysis.
  • Analysis-Ready Data: Transform and prepare your data for immediate use.

Experience hassle-free data migration with Hevo. Explore Hevo’s capabilities with a free personalized demo and see how you can benefit.

Get Started with Hevo for Free

What is the purpose of Microsoft MSMQ?

Using MSMQ, you can allow several applications running at different times to talk with each other across a combination of heterogeneous networks(a network that uses multiple network architectures and operating systems) and systems that may be temporarily offline. MSMQ provides a messaging system that facilitates a queue to hold messages that are generated by multiple sending applications and read by multiple receiving applications.

Key Applications of Microsoft MSMQ

MSMQ ensures message delivery, effective routing, security, and priority-based messaging. Owing to MSMQ’s flexibility, you can perform both asynchronous and synchronous messaging with high performance. Check out the following scenarios where you can employ MSMQ to your advantage:

  • Financial Services: Ensure fluent & secured message delivery for electronic commerce use cases.
  • Portable Applications: Effective communication between embedded systems in an automatic baggage system that routes baggage through airports.
  • Seamless Sales: Empower sales automation software for traveling sales representatives with efficient messaging.
  • Fluent Workflow: MSMQs provide you with the ability to build smooth workflows that update your systems. You can design an agent that interacts with each system and also minimizes the effect of any changes done in one system on others. It loosens the coupling between different systems and makes it super easy to upgrade individual systems.

Key Types of Message Queuing Applications

You can classify the Message Queuing Applications into the following 2 categories:

  • Receiving Applications 
  • Sending Applications  

Receiving Applications

MSMQ’s Receiving applications can read the message from a queue using 2 different methods. It can either read the message & leave it there in the queue or extract the message, thereby taking out the message from the queue. It is to be noted that you don’t require access to the directory service as messages can be sent to the queue and read from the queue without it.

Sending Applications

The Sending applications send the messages directly to the queue and not to the receiving application. This removes any dependency on the receiving application to be available for receiving the message from the sending application. 

Understanding Microsoft MSMQ Operations

To understand how MSMQ can simplify your messaging workflow, you can go through the following basic MSMQ operations:

  • Creating a Queue 
  • Locating Queues
  • Opening Queues
  • Navigating Queues

Creating a Queue

To start with MSMQ, you can begin with creating a simple public or private queue based on the queue path name provided. This example introduces you to a basic application-defined function that returns the public or private format name of the queue created and the length of the format name including the null-terminating character.

While defining a queue, you can go through the following set of simple steps:

  • Step 1:  To start with MSMQ, begin with defining the MQQUEUEPROPS structure.
  • Step 2: Now, configure the queue properties. For this example, the following properties are considered:
    • PROPID_Q_PATHNAME: This is needed to create the queue. You can set it to the UNC or DNS path name of the queue.
    • PROPID_Q_LABEL: Identifies the queue.
  • Step 3: After setting the properties, start initializing the MQQUEUEPROPS structure.
  • Step 4: Finally, call the MQCreateQueue function to create the queue.
#include "windows.h"  
#include "mq.h"  
#include "tchar.h"  
#define BUFLEN = 256 ;  
  
HRESULT CreateMSMQQueue(  
                        LPWSTR wszPathName,   
                        PSECURITY_DESCRIPTOR pSecurityDescriptor,  
                        LPWSTR wszOutFormatName,  
                        DWORD *pdwOutFormatNameLength  
                        )  
{  
  
  // Setting the maximum number of queue properties to 2.
  const int NUMBEROFPROPERTIES = 2;  
  
  // Build the queue property structure and the structures required to initialize it.  
  MQQUEUEPROPS   QueueProps;  
  MQPROPVARIANT  aQueuePropVar[NUMBEROFPROPERTIES];  
  QUEUEPROPID    aQueuePropId[NUMBEROFPROPERTIES];  
  HRESULT        aQueueStatus[NUMBEROFPROPERTIES];  
  HRESULT        hr = MQ_OK;  
  
  // Check the input parameters.  
  if (wszPathName == NULL || wszOutFormatName == NULL || pdwOutFormatNameLength == NULL)  
  {  
    return MQ_ERROR_INVALID_PARAMETER;  
  }  
  
  // Configure the queue properties.  
  DWORD cPropId = 0;  
  aQueuePropId[cPropId] = PROPID_Q_PATHNAME;  
  aQueuePropVar[cPropId].vt = VT_LPWSTR;  
  aQueuePropVar[cPropId].pwszVal = wszPathName;  
  cPropId++;  
  
  WCHAR wszLabel[MQ_MAX_Q_LABEL_LEN] = L"Test Queue";  
  aQueuePropId[cPropId] = PROPID_Q_LABEL;  
  aQueuePropVar[cPropId].vt = VT_LPWSTR;  
  aQueuePropVar[cPropId].pwszVal = wszLabel;  
  cPropId++;  
  
  // Initialize the MQQUEUEPROPS structure.  
  QueueProps.cProp = cPropId;               // Number of properties  
  QueueProps.aPropID = aQueuePropId;        // IDs of the queue properties  
  QueueProps.aPropVar = aQueuePropVar;      // Values of the queue properties  
  QueueProps.aStatus = aQueueStatus;        // Pointer to the return status  
  
  // Call MQCreateQueue to create the queue.  
  WCHAR wszFormatNameBuffer[BUFLEN];  
  DWORD dwFormatNameBufferLength = BUFLEN;  
  hr = MQCreateQueue(pSecurityDescriptor,         // Security descriptor  
                     &QueueProps,                 // Address of queue property structure  
                     wszFormatNameBuffer,         // Pointer to format name buffer  
                     &dwFormatNameBufferLength);  // Pointer to receive the queue's format name length in Unicode characters not bytes.  
  
  // Return the format name if the queue is created successfully.  
  if (hr == MQ_OK || hr == MQ_INFORMATION_PROPERTY)  
  {  
    if (*pdwOutFormatNameLength >= dwFormatNameBufferLength)  
    {  
      wcsncpy_s(wszOutFormatName, *pdwOutFormatNameLength - 1, wszFormatNameBuffer, _TRUNCATE);  
      // ************************************  
      // You must copy wszFormatNameBuffer into the   
      // wszOutFormatName buffer.  
      // ************************************  
      wszOutFormatName[*pdwOutFormatNameLength - 1] = L'';  
      *pdwOutFormatNameLength = dwFormatNameBufferLength;  
    }  
    else  
    {  
      wprintf(L"The queue was created, but its format name cannot be returned.n");  
    }  
  }  
  return hr;  
}

If you try to pass a NULL pointer to a SECURITY_DESCRIPTOR structure to this function in pSecurityDescriptor, you will eventually get a queue with the default security descriptor

Locating Queues

Using the properties of a queue, you can easily query the directory service for a set of public queues in MSMQ. For instance, you can query a directory service for all the public queues with a specific label or a specific queue identifier. You can also locate private queues in MSMQ 3.0. 

Consider the following image shown below that depicts a query that retrieves 2 queues based on the service type GUID. Here, the calling application opens up the queue to send or reds a message. You can use this type of query for helping with load balancing when you need to send a message to a queue on a separate machine.

Image Source

The calling application must follow a defined process to perform a query depending on following type of calls made:

  • API function calls: Fo locating a query, you can define a condition based on a valid queue property other than the queue pathname. The calling application must mention the queue property that MSMQ returns as a query result. 
  • COM Methods calls: For this COM, your search criteria are limited to queue labels, queue identifiers, service types, creation times, modification times, and multicast addresses. MSMQ returns an MSMQQueueInfos object that defines a query, queries a directory service, and provides a method that returns an MSMQQueueInfo object for each queue found in the query.

You can use the following API functions and COM methods to locate public queues:

  • MQLocateBegin
  • MQLocateNext
  • MQLocateEnd
  • MSMQQuery.LookupQueue

Opening Queues

Another important MSMQ operation is opening a queue. It is essential for an application to first open a queue before starting sending messages to a queue or receiving messages from a queue. Once your application has opened a queue, MSMQ returns a queue handle that allows you the application to execute the following tasks:

  • Send messages to one or more (in MSMQ 3.0) destination queues.
  • Look at or extract messages from a single queue.
  • Create cursors for navigating through the queue (Message Queuing COM components provide a single implicit cursor each time a queue is open).
  • Create format names.
  • Close the queue.

While making the call to open a queue, an application has to ensure to mention the following 3 details:

  • The queue format name.
  • The access mode.
  • The share mode.

Navigating Queues

When you are trying to extract a message, the receiving application can use the cursor or the message lookup identifier (introduced in MSMQ 3.0) to navigate the messages in the queue. For cases when you use the cursor, the receiving application starts at the beginning of the queue and moves to the end of the queue in order. If you use a message lookup ID, the receiving application can start at the beginning of the queue, the message associated with a particular lookup ID, or the end of the queue. After reading the message via the message identifier, the receiving application can move to the top or bottom of the queue.

Understanding Microsoft MSMQ Functions 

MSMQ provides a robust architecture that allows you to manage queues and messages for Message Queuing applications. The Message Queuing API contains functions for:

  • Creating, opening, and deleting queues.
  • To find existing queues and messages in the queue.
  • To send and read messages in the queue. 
  • To set and extract properties.

You can go through the following list of functions:

  • MQCreateCursor
  • MQCloseCursor
  • MQFreeMemory
  • MQSetQueueProperties
  • MQGetMachineProperties

MQCreateCursor

Using the MQCreateCursor function, you can create a cursor for a particular queue and returns a handle to the cursor. This cursor is enables you to maintain a certain location in a queue when reading the queue’s messages. The sample syntax for this function is as follows:

HRESULT APIENTRY MQCloseCursor(  
  HANDLE hCursor    
);

This function has 2 parameters:

  • queue: This represents a handle to the queue for which you want to create a cursor.
  • phCursor: It denotes a pointer to a variable that receives the resulting cursor handle.

MQCloseCursor

This MSMQ function closes a particular cursor specified by you and frees up the resources related to that cursor. 

You can use this function via the following syntax:

HRESULT APIENTRY MQCloseCursor(  
  HANDLE hCursor    
);

This function has only 1 parameter hCursor that represents a handle to the cursor you want to close.

MQFreeMemory

You can employ this MSMQ function to free up memory allocated by Message Queuing. You execute this function by using the following syntax:

Copy
VOID MQFreeMemory(  
  PVOID pvMemory    
);

This function has only 1 parameter pvMemory that demonstrates a pointer to the memory to be freed.

MQSetQueueProperties

Using this MSMQ function, you can configure the properties of a particular queue.

Copy
HRESULT APIENTRY MQSetQueueProperties(  
  LPCWSTR lpwcsFormatName,    
  MQQUEUEPROPS * pQueueProps    
);  

This function has the following 2 parameters: 

  • lpwcsFormatName: This acts as a pointer to the format name string of the queue whose properties you want to configure. You can use a public or private format name to specify the queue. You can only use a direct format name to configure the properties of a local private queue.
  • pQueueProps: It is a pointer to the MQQUEUEPROPS structure that mentions the properties you want to configure.

For the input, the cProp member of MQQUEUEPROPS mentions the number of properties you want to configure, the aPropID array helps in mentioning their property identifiers, and the aPropVar array indicates the new values of the particular properties.

For the output, the optional aStatus array(if included in MQQUEUEPROPS

)indicates the status of the properties.

MQGetMachineProperties

This MSMQ function extracts details about a queue manager computer. You can create this function via the following syntax:

Copy
HRESULT APIENTRY MQGetMachineProperties(  
  LPCWSTR lpwcsMachineName,    
  const GUID * pguidMachineID,         
  MQQMPROPS * pQMProps           
); 

This function has the following parameters:

  • lpwcsMachineName: This is the name of the queue manager computer you want to access. You have to mention the NetBIOS or DNS name of the computer. If you are parameter is used, set pguidMachineID to NULL.
  • pguidMachineID: The identifier of the queue manager computer you want to access. If this parameter is used, set lpwcsMachineName to NULL.
  • pQMProps: It is a pointer to a queue manager properties structure (MQQMPROPS) mentioning which properties to extract.

Apart from these 5 functions, you can go through the following table to learn about more MSMQ functions:

Function Description
MQADsPathToFormatName Translates the ADs path of a queue, queue alias, or distribution list into a format name.
MQBeginTransaction Creates an internal Message Queuing transaction object that can be used to send messages to a queue or read messages from a queue.
MQCloseQueue Closes a given queue.
MQCreateCursor Creates a cursor for a specific queue and returns its handle.
MQCreateQueue Creates a public or private queue.
MQDeleteQueue Deletes a queue from the directory service or from the local computer.
MQFreeSecurityContext Frees the memory allocated by MQGetSecurityContext.
MQGetOverlappedResult Retrieves the Message Queuing receives success or error code from the OVERLAPPED structure used to retrieve a message asynchronously.
MQGetPrivateComputerInformation Retrieves information about the local computer without accessing the directory service.
MQGetQueueProperties Retrieves the specified set of properties for a specific queue.
MQGetQueueSecurity Retrieves information from the access control security descriptor of the specified queue.
MQGetSecurityContext (Superseded by MQGetSecurityContextEx.) Retrieves security information needed to attach a certificate to a message for authentication.
MQGetSecurityContextEx (Introduced in Windows® 2000 Service Pack 2, supersedes MQGetSecurityContext.) Retrieves the security information needed to attach a certificate to a message for authentication.
MQHandleToFormatName Returns a format name for the queue based on its handle.
MQInstanceToFormatName Returns a format name for the queue based on the identifier provided.
MQLocateBegin Starts a query to locate a public queue, returning a query handle.
MQLocateEnd Ends a query, releasing the resources associated with the query.
MQLocateNext Retrieves the requested queue information from the query.
MQMgmtAction (Introduced in MSMQ 3.0.) Changes the state of a computer or a queue.
MQMgmtGetInfo (Introduced in MSMQ 3.0.) Retrieves information about a computer or a queue.
MQOpenQueue Opens a queue for sending, peeking at, retrieving, or purging messages.
MQPathNameToFormatName Returns a format name based on the Message Queuing path name provided.
MQPurgeQueue (Introduced in MSMQ 3.0.) Deletes all of the messages in a queue.
MQReceiveMessage Allows you to read messages in the queue.
MQReceiveMessageByLookupId (Introduced in MSMQ 3.0.) Peeks at or retrieves messages in the queue based on message lookup identifiers.
MQSendMessage Sends a message to the queue corresponding to the handle hDestinationQueue.
MQSetQueueSecurity Sets the access control security descriptor of a queue.
MQMoveMessage Moves messages between a queue and its subqueue, or between two subqueues within the same main queue.
MQMarkMessageRejected Marks a message in a queue as rejected.

Conclusion

In this article, you have learned about MSMQ and how it works. MSMQ ensures safe, timely, and priority-based message delivery with both asynchronous and synchronous messaging. It is built into Windows but not pre-installed and supports operations like creating, deleting, and navigating message queues. Although MSMQ simplifies messaging, managing data across multiple systems for analysis is complex and resource-intensive.

Cloud-based ETL tools like Hevo streamline this by automating data integration, transformation, and loading into your desired destination, thus enabling efficient business analytics. Hevo Data, a No-code Data Pipeline can transfer data in Real-Time from a vast sea of 150+ sources to a Data Warehouse, BI Tool, or a Destination of your choice. Try a 14-day free trial and experience the feature-rich Hevo suite firsthand. Also, check out our unbeatable pricing to choose the best plan for your organization.

FAQs

1. What is the difference between RabbitMQ and MSMQ?

RabbitMQ is an open-source, cross-platform message broker with support for multiple protocols. MSMQ is a Microsoft-specific message queuing system mainly for Windows environments.

2. What is the limit of MSMQ?

MSMQ supports message sizes up to 4 MB by default but can be configured to handle up to 100 MB. Its maximum queue depth is also 2 billion messages.

3. Is MSMQ support in .NET core?

MSMQ is not natively available in .NET Core. However it can be used with .NET Core by third party libraries or through inter-process communication mechanisms.

Sanchit Agarwal is an Engineer turned Data Analyst with a passion for data, software architecture and AI. He leverages his diverse technical background and 2+ years of experience to write content. He has penned over 200 articles on data integration and infrastructures, driven by a desire to empower data practitioners with practical solutions for their everyday challenges.

Microsoft Message Queue (MSMQ) Server is a messaging protocol developed by Microsoft that allows applications running on separate servers/processes to communicate with each other. MSMQ is part of Microsoft’s messaging infrastructure, providing a way for applications to send and receive messages over the network asynchronously.

MSMQ is often considered a legacy technology, as it has been around since the late 1990s. It was more commonly used in enterprise applications for system integration and in scenarios where offline capabilities were needed.

In this article:

  1. What is MSMQ?
  2. Key Features and Benefits of MSMQ
  3. MSMQ in Action: Usage Scenarios
    • Usage Scenario
    • Practical Coding Example
  4. Comparing MSMQ with Modern Alternatives
  5. The Legacy of MSMQ and Current Trends
  6. Conclusion
  7. References

1. What is MSMQ?

Microsoft Message Queue (MSMQ) is a technology developed by Microsoft for providing asynchronous communication between distributed applications in an enterprise environment. MSMQ allows applications to send and receive messages via queues, which are stored on the file system and managed by the MSMQ service. This message queuing system enables decoupled communication, where applications do not need to interact with each other directly or be online simultaneously to exchange messages.

Microsoft Message Queue Server

Microsoft Message Queue Server

Asynchronous Messaging in MSMQ:

  • Queue-Based Communication: Applications send messages to queues, and recipient applications retrieve these messages from the queues. This setup allows for asynchronous processing, where the sender and receiver do not need to operate or be available at the same time.
  • Handling Network Fluctuations: MSMQ is designed to handle intermittent network connections gracefully. Messages are queued locally and transmitted once the network is available, ensuring message delivery is not dependent on real-time network conditions.

2. Key Features and Benefits of MSMQ

Key Features

MSMQ comes with a host of features that make it a robust solution for enterprise-level message queuing:

Reliable Delivery:

  • MSMQ guarantees the delivery of messages, ensuring that each message is delivered once and only once. This reliability is crucial for applications where data integrity is paramount.

Transactional Messages:

  • MSMQ supports transactional processing of messages. This means that either all messages in a transaction are successfully delivered and processed, or none are, maintaining data consistency across distributed systems.

Security:

  • Security in MSMQ is multifaceted, including encryption for message privacy, authentication to ensure messages come from legitimate sources, and authorization controls to manage who can send and receive messages.

Offline Operations:

  • MSMQ can store messages in queues even when the network is down or the recipient application is offline. This capability ensures that message processing and delivery can continue once the application or network becomes available.

Benefits in Enterprise Environments

  • Decoupling of Applications: MSMQ allows applications to operate independently, enhancing system scalability and robustness.
  • Improved Performance: By enabling asynchronous communication, MSMQ allows applications to offload heavy processing, thereby not blocking other operations.
  • Flexibility and Scalability: MSMQ supports a wide range of scenarios from simple point-to-point messaging to complex routing and prioritization of messages, making it versatile for various enterprise needs.
  • Enhanced Reliability: The assurance of message delivery and transactional integrity makes MSMQ suitable for critical business processes where data accuracy is essential.

In enterprise environments, MSMQ’s ability to provide reliable, secure, and scalable messaging solutions makes it an important tool in the arsenal of system integrators and application developers, particularly in scenarios requiring robust communication mechanisms.

3. MSMQ in Action: Usage Scenarios

MSMQ Usage Scenarios

Microsoft Message Queue (MSMQ) finds its utility in a variety of scenarios, particularly in environments where reliable, asynchronous communication is essential. Its use cases span across different domains, showcasing its flexibility and robustness.

System Integration:

  • In large enterprises, different systems often need to communicate with each other. MSMQ facilitates this by allowing systems to exchange information through messages, regardless of the languages or platforms they are built on. This capability is invaluable in scenarios where legacy systems need to be integrated with newer applications.

Business Process Automation:

  • MSMQ is instrumental in automating business processes. For instance, in a supply chain management system, MSMQ can be used to queue orders, inventory updates, and shipping notifications, ensuring that each component of the supply chain communicates effectively, even under heavy loads or network disruptions.

Financial Transactions:

  • The financial sector leverages MSMQ for transaction processing. The transactional messaging feature ensures that operations such as transfers or payments are completed reliably and in the correct order, a critical requirement in financial systems.

Healthcare Applications:

  • MSMQ is used in healthcare applications for transmitting patient data, lab results, and other critical information between systems. Its ability to function offline ensures that data transfer is not hindered by intermittent network issues, crucial in healthcare settings.

Retail Operations:

  • In retail, MSMQ can manage communication between point-of-sale systems and inventory management systems, helping in keeping stock levels updated in real-time and processing sales transactions efficiently.

3.2 Practical Coding Example

Below is a simple example of how a basic MSMQ application might be coded in C#. This example includes creating a queue, sending a message to the queue, and receiving a message from the queue. Note that this is a basic demonstration intended for educational purposes and may need to be adapted for specific use cases.

First, ensure that the MSMQ feature is installed on your Windows machine and add a reference to System.Messaging in your project.

Creating a Queue:

using System.Messaging;

...

// Check if a specific queue exists. If not, create it.
string queuePath = @".\Private$\MyTestQueue";
if (!MessageQueue.Exists(queuePath))
{
    MessageQueue.Create(queuePath);
}

Sending a Message to the Queue:

...

// Create a new message queue instance
MessageQueue myQueue = new MessageQueue(queuePath);

// Create a new message
Message myMessage = new Message();
myMessage.Body = "Hello MSMQ!";

// Send the message to the queue
myQueue.Send(myMessage);

Receiving a Message from the Queue:

...

// Set the formatter to indicate body type
myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(string) });

// Receive and format the message
try
{
    Message myReceivedMessage = myQueue.Receive();
    string messageContent = myReceivedMessage.Body.ToString();
    Console.WriteLine($"Received message: {messageContent}");
}
catch (MessageQueueException e)
{
    Console.WriteLine(e.Message);
}

This code demonstrates a basic use case of MSMQ where a message is created, sent to a queue, and then received from the queue. Remember, for a real-world application, you’ll need to handle exceptions more robustly and consider security and transactional messaging based on your requirements.

4. Comparing MSMQ with Modern Alternatives

While MSMQ has been a stalwart in the message queuing arena, the landscape of messaging technologies has evolved with newer players like RabbitMQ, Apache Kafka, and various cloud-native services.

RabbitMQ:

  • A widely-used open-source message broker, RabbitMQ supports multiple messaging protocols. It is known for its flexibility, ease of deployment, and support for complex routing. Unlike MSMQ, RabbitMQ offers a broader range of features for message management and monitoring.

Apache Kafka:

  • Designed for high throughput and scalability, Apache Kafka is more than just a messaging system; it’s a distributed streaming platform. Kafka excels in scenarios involving large amounts of data, providing capabilities for real-time analytics. It’s a different paradigm compared to MSMQ, focusing more on data streaming rather than traditional queuing.

Cloud-Native Services:

  • Services like AWS SQS, Azure Queue Storage, and Google Cloud Pub/Sub provide scalable, managed queueing services with deep integration into their respective cloud ecosystems. These services offer high availability, automatic scaling, and ease of maintenance, which are challenging to achieve with self-managed solutions like MSMQ.

Comparison:

  • MSMQ’s strengths lie in its simplicity, integration with Windows-based systems, and support for offline operations. However, when it comes to scalability, cross-platform support, and advanced monitoring and management features, modern alternatives often have the upper hand. For instance, RabbitMQ and Kafka provide better support for complex routing and distributed systems, while cloud-native services offer the advantages of cloud scalability and reduced maintenance overhead.

5. The Legacy of MSMQ and Current Trends

MSMQ, a venerable component of Microsoft’s technology portfolio, retains its relevance in certain legacy systems. In today’s landscape, the focus has shifted towards distributed, scalable, and cloud-native messaging solutions, positioning MSMQ more as a specialized tool within a broader, more diverse messaging toolkit.

6. Conclusion

Historically, MSMQ played a pivotal role in enabling asynchronous communication in IT environments, particularly within the Microsoft ecosystem. Its legacy continues in specific use cases where its particular features align with business needs, even as the industry gravitates towards more modern, scalable messaging platforms.

7. References

  1. “Pro MSMQ – Microsoft Message Queue Programming” by Arohi Redkar, Ken Rabold, Richard Costall, Scot Boyd, Carlos Walzer.
  2. “Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions” by Gregor Hohpe and Bobby Woolf
  3. “Installing Message Queuing (MSMQ)“, Microsoft Learn
  4. “Distributed Systems: Concepts and Design” by George Coulouris, Jean Dollimore, Tim Kindberg, and Gordon Blair

Today’s enterprise applications are multi-tiered and interop with many other systems in the enterprise. Users demand easy to use, responsive and sophisticated applications or they will avoid using it. Reliability and responsiveness do not come easy. Reliable exchange and processing of data (messages) in itself is a time consuming and complex undertaking. Microsoft Message Queue server, short MSMQ, provides exactly that — guaranteed and reliable message delivery. It provides an easy way to send messages between different applications or to process messages asynchronously.

Many back-end processes can be long-running. You want to separate these processes from the user-interaction. You want to be able to store the message and process it asynchronously while the user can go on and do other things. Then, when the message has been processed you want to provide a means of notifying the user about its result. Asynchronous processing is key for being responsive to the user and can also become complex. Think about the following example in a typical eCommerce application. The user purchases some goods from your site and uses a credit card for its payment. In real l¯ife that means calling out to a credit merchant to verify the credit card and securing the funds, shipping of the goods, updating your inventory status and making sure to re-stock your warehouse. Some of that you want to do in real time and some of that you want to do asynchronously. But all these interactions need to happen in a reliable fashion. You can’t charge the customer and then for whatever technical reasons not ship the goods. You also want to be assured that your inventory status gets updated and sold goods are replaced. Any technical brake-down in that process means a negative experience for customers and high unnecessary costs. Reliable and guaranteed message delivery and processing avoids all this. And any messaging solution like «Microsoft Message Queue» server can make it easy to provide this guaranteed, reliable and asynchronous message processing.

Overview of Microsoft Message Queue server

MSMQ comes as part of the Windows OS (MSMQ 1.0 with Windows NT 4, Windows 95 and Windows 98; MSMQ 2.0 with Windows 2000; MSMQ 3.0 with Windows 2003 and Windows XP). This article concentrates on MSMQ 3.0 running on Windows 2003. You can find a number of whitepapers and information on the Microsoft site (click here). You can install MSMQ through the «Add/Remove Windows Components» (under the component «Application Server» and «Message Queuing»).

Queues are used to store and route messages. Applications send messages to queues and receive/read messages from queues. There are two different types of queues — private and public queues. Private queues do not provide any routing. Applications can send messages to private queues and other applications or other layers of the same application can then read these messages from the same queue of the same MSMQ instance. Private queues are accessed through «Machine name\Private$\Queue name», for example «MyMachine\Private$\Orders». If MSMQ is installed on the same machine as your application then you can replace the machine name with a dot, for example «.\Private$\Orders». Private queues do not provide any routing but can still be accessed remotely. So you can have a workgroup where one machine has MSMQ installed and all other machines in that workgroup can access this MSMQ instance. Private queues are your choice if all clients/machines accessing the queue are in close proximity and have a fast and reliable connection between them. A good example would be an application which splits up the order placement, order processing and order processed notification into three separate layers but all layers are in close proximity. All three layers can use the same MSMQ instance with one or multiple private queues to exchange messages reliable and easy.

Public queues on the other hand provide message routing. Public queues are your choice if your applications are distributed or have to deal with unreliable communication mediums. A good example would be to have order placement and order fulfillment in different geographical locations or even be performed by different companies. Take an eCommerce portal which resells products from other merchants. You want to take the orders with your application and then reliably route these orders to each merchant for the fulfillment. This means you might have to send these orders over the internet to merchants residing all over the country — a distributed environment with an unreliable communication medium in between. You would have a MSMQ server in close proximity to the servers hosting your eCommerce application and have a public queue for each merchant. The eCommerce application would place orders in the appropriate public queues and then rely on MSMQ to guarantee the delivery. Merchants would rely on the same means to send notifications back to the eCommerce site that orders have been processed. Public queues are accessed through «Machine name\Queue name», for example «MyServer\Orders». You can also replace the machine name with a dot if your application resides on the same machine as MSMQ.

MSMQ can be deployed in two modes — workgroup mode or domain mode. The workgroup mode provides only private queues. So there is no message routing available in the workgroup mode. The domain mode provides private queues and public queues. But the domain mode requires that the machine you install MSMQ on is part of a domain and that the domain uses Active Directory. When you install MSMQ in the workgroup mode you only require the components «Common» and «Triggers». When installing in the domain mode you need the components «Common», «Active Directory Integration», «Routing Support» and «Triggers». When installing in domain mode you can set up sites and site links which determine which queues replicated and how messages are routed. This goes beyond this article.

Private queues are a bit faster then public queues. Think about your requirements to determine which type of queue you need to use. The type of queue determines which MSMQ mode you need. If all clients accessing MSMQ are in close proximity and have a fast and reliable medium to access it, then use private queues and install MSMQ in workgroup mode. If you have a distributed environment or an unreliable communication medium you need message routing which requires public queues and you install MSMQ in domain mode. MSMQ installs two windows services — «Message Queuing» and «Message Queuing Triggers».

There is also an administrative interface which you find under «Computer Management». Under the item «Services and Applications» you find an entry called «Message Queuing». You can view all private and public queues. You can create new queues, edit the properties of existing queues and also delete existing queues. Under each queue you find three items:

  • Queue messages — Shows you all the messages currently sitting in the queue. You can view the properties of each message but you can not change it. You can not create a new message or delete an individual message. You can remove all messages by right clicking on «Queue Messages» and selecting «All Tasks | Purge».
  • Journal Messages — When you create a queue you can also enable a «Journal». This means when a message is received/read from that queue a copy will be placed into the journal of that queue. So you have a copy of every message read and processed from that queue. Regularly purge messages from the Journal which are no longer needed otherwise it will grow for ever.
  • Triggers — Allows you to register a trigger to be called when a message is placed into this message queue. When setting up the trigger you can specify whether a COM component is called or an external executable (more on this later on).

Beside private and public queues you find also an entry called «System Queues». These are system generated queues which you can not modify or remove. Underneath you find three queues:

  • Journal messages — When you have enabled the «Journal» of a queue then a copy of the message is placed in the journal of that queue when read/received. If the journal of the queue is not enabled then a copy is placed in the journal under system queues. This gives you control to have a journal per queue or one system journal for all queues.
  • Dead-letter messages — Places a copy of every message which can not be delivered or expires before it is delivered or expires before it is received/read.
  • Transactional dead-letter messages — Same as the dead-letter messages queue but for all transactional messages. See more later on about transactional messages.

You can also programmatically create and delete queues as well as set the properties of existing queues.

A look at MSMQ and the .NET framework

The .NET framework provides a number of classes to work with MSMQ, located in the System.Messaging namespace. The two most important classes are MessageQueue and Message. The MessageQueue object is used to open or delete existing queues and create new ones. It is also used to send and receive messages. The Message object itself is used to encapsulate the data you want to send or receive into a message.

The following code snippet shows how to create a new message queue. First you want to check with MessageQueue.Exists if the queue already exists. If not, then you can create a new queue with MessageQueue.Create and provide the queue path plus if the queue is transactional or not. The queue path consists of three parts — the machine name, if it is a private queue or not plus the name of the queue. If you address a MSMQ instance on the same machine your code runs on, then you can use instead of the machine name also a dot. A public queue path uses «Machine name\Queue name» and a private queue path «Machine name\Private$\Queue name». The label of the queue is a user friendly name of the queue. Queues can also participate in transactions. MSMQ distinguishes between internal and external transactions. Internal transactions only encompass MSMQ. You start a transaction with a MessageQueueTransaction object, then send your messages with a MessageQueue object and at the end commit or abort the transaction. Aborting an internal transaction will roll back all send messages, meaning no message will be send. Messages can only be read/received after the internal transaction has been committed. External transaction means the component which sends the messages to a queue is registered in COM+ and participates in a COM+ transaction. In this case you use the COM+ transaction controls which itself use the MSDTC «Distributed Transaction Coordinator». The MSDTC will commit or abort the transaction. Otherwise internal and external transactions behave the same way. You can us internal or external transactions only when the queue has been marked as transactional. If the queue has been marked as transactional you can send only transactional messages and if it has been marked as «not transactional» then you can only send non transactional messages.

// check to make sure the message queue does not exist already
if (!MessageQueue.Exists(QueueName))
{
    // create the new message queue and make it transactional
    MessageQueue MQ = MessageQueue.Create(QueueName,true);
    // set the label name and close the message queue
    MQ.Label = LabelName;
    MQ.Close();
} 

The next code snippet shows how to delete an existing queue. First you check with MessageQueue.Exists if the queue exists then you delete it with MessageQueue.Delete. Message queues have also windows security ACLs assigned. This allows you to control access to queues through standard windows security. The security for queues can be set through the «Computer Management» interface by bringing up the properties window of a queue. If you do not have the right to delete the queue then MessageQueue.Delete raises a MessageQueueException exception, which for example is handled in the code snippet below.

// check to make sure the message queue does exist
if (MessageQueue.Exists(QueuePath))
{
    try
    {
        MessageQueue.Delete(QueuePath);
    }
    catch (MessageQueueException)
    {
        MessageBox.Show("You do not have the rights to delete the queue.");
    }
}

You can also enumerate a list of all message queues present on a MSMQ instance. To get a list of public queues you call GetPublicQueues, GetPublicQueuesByCategory, GetPublicQueuesByLabel or GetPublicQueuesByMachine on the MessageQueue class. To get the list of private queues you call MessageQueue.GetPrivateQueuesByMachine. The method names are self explanatory. All of them return an array of MessageQueue objects which you then use to obtain information about each queue. The code snippet below gets the list of private queues and then loops through each to get the queue name and label and if the queue is transactional or not.

// get the list of message queues
MessageQueue[] MQList = MessageQueue.GetPrivateQueuesByMachine(MachineName);
// check to make sure we found some private queues on that machine
if (MQList.Length >0)
{
    // allocate a string array which holds for each queue the name, path, etc.
    string[,] MQNameList = new string[MQList.Length, 3];
    // loop through all message queues and get the name, path, etc.
    for (int Count = 0; Count < MQList.Length; Count++)
    {
        MQNameList[Count, 0] = MQList[Count].QueueName;
        MQNameList[Count, 1] = MQList[Count].Label;
        MQNameList[Count, 2] = MQList[Count].Transactional.ToString();
    }
}

A look how to send and receive messages with the .NET framework

You use a Message object to send a message to a queue. First you create a new MessageQueue object and pass along the queue path you want the message to be send to. Next you create a Message object and pass along the object which contains the data you want to send. When the message is send, this object will get serialized and stored in the message body. The default serialization object used is the XmlMessageFormatter, which serializes the object to XML. You can also use a BinaryMessageFormatter, which formats the object into binary format, or an ActiveXMessageFormatter which serializes in a format which is compatible with COM message queuing components. This formatter works with most primitive types and requires for objects the implementation of the IPersistStream interface. If you want to use a formatter other then the default one then you need to create an instance of it and assign it to the Formatter property of the message object. Then you set the properties of the message object as required and finally call the Send() method on the message queue object you created. At the end you close the queue by calling Close() on the message queue object. Here is a sample code snippet:

// create a message queue object
MessageQueue MQueue = new MessageQueue(MessageQueuePath);
// create the message and set the base properties
Message Msg = new Message(TheObject);
Msg.ResponseQueue = new MessageQueue(ResponseMessageQueuePath);
Msg.Priority = MessagePriority.Normal;
Msg.UseJournalQueue = true;
Msg.Label = Label;
// we want a acknowledgement if received or not in the response queue
Msg.AcknowledgeType = AcknowledgeTypes.FullReceive;
Msg.AdministrationQueue = new MessageQueue(ResponseMessageQueuePath);
// send the message
MQueue.Send(Msg);
// close the mesage queue
MQueue.Close();

The message object itself provides you with a lot of control about the message you are sending. You can set a user friendly label with the Label property. You can set the priority of the message with the Priority property using a value of the MessagePriority enumeration. If you want the message to be placed in a journal when received/read then set the UseJournal property on the message to true. The AcknowledgeType property provides you control over which acknowledgement you require using a value of the AcknowledgeTypes enumeration. For example setting it to FullReceive means you will get an acknowledgement if it has been received/read but also if the message is undeliverable or expired. The acknowledgement is sent to the queue specified by the AdministrationQueue property of the message. Via the TimeToBeReceived property you can specify by when the message needs to be received/read otherwise it will expire and be removed by MSMQ. You don’t set an absolute date/time but rather a time span using a TimeSpan object. There are many more properties you can set on the Message object. Please refer to the MSDN documentation for a complete list.

You can use MessageQueueTransaction to start an internal transaction. You create an instance of that class and call BeginTransaction(). For every message you send and want to be part of this transaction you pass along this transaction object in the Send() method. When done you call Commit() or Abort() on the transaction object. The messages you send as part of a transaction will only be available to read by the time you call Commit(). Don’t forget to still call Close() on the message queue object. Using a transaction works only with queues which are marked as transactional. Here is a code snippet:

// create a message queue transaction and start it
MessageQueueTransaction Transaction = new MessageQueueTransaction();
Transaction.Begin();
// create a message queue
MessageQueue MQueue = new MessageQueue(MessageQueuePath);
// create the message and set the base properties
Message Msg = new Message(TheObject);
// send the message as part of the transaction
MQueue.Send(Msg, Transaction);
// commit the transaction
Transaction.Commit();
// close the mesage queue
MQueue.Close();

Reading a message will automatically remove it from the queue and if the message property UseJournal has been set to true a copy will be placed in the journal. You read messages by calling Receive() on the message queue object. This call is synchronous and blocks till a message is available. An overloaded version of Receive() allows to specify a time span, the time how long the call will wait to receive a message. The Receive() method returns a Message object. The Body property allows you to access the object which was stored in the message when sent. It is important to use the same formatter type when reading and sending the message or otherwise an exception will be thrown. For example, if you used a BinaryMessageFormatter when sending the message then you need to create a BinaryMessageFormatter object and assign it to the Formatter property on the message queue object before you call the Receive() method. The XmlMessageFormatter is not able to recognize which type has been serialized into XML. Therefore you need to set the TargetType property on the XmlMessageFormatter to the type you have stored in the message. Through this the XML formatter knows which type to create and de-serialize out of the message. For performance improvement Receive() reads by default only a handful of properties from the message. Accessing a message property which has not been read throws an InvalidOperationException exception. Before you call Receive() you set on the message queue object through the MessageReadPropertyFilter property which message properties you want to be read. Call MessageReadPropertyFilter.SetAll() if you want to read every property of the message. Here is a code snippet:

// open the selected message queue
MessageQueue MQueue = new MessageQueue(ListOfMessageQueues.SelectedNode.Name);
MQueue.MessageReadPropertyFilter.SetAll();
// the target type we have stored in the message body
((XmlMessageFormatter)MQueue.Formatter).TargetTypes = new Type[] { typeof(Order) };
try
{
    // read the message from the queue, but only wait for 5 sec
    System.Messaging.Message Msg = MQueue.Receive(new TimeSpan(0, 0, 5));
    // read the order from the message body
    Order Order = (Order)Msg.Body;
    // close the message queue
    MQueue.Close();
}
// no message present to read
catch (MessageQueueException)
{
    MessageBox.Show(this, "There is no message in the queue at this time.");
}

The code snippet specifies a time span for how log to wait for a message. If no message is present within that timeout, then a MessageQueueException exception is thrown. You can also read messages asynchronously. First you register an event handler of the type ReceiveCompletedEventHandler with the property ReceiveCompleted on the message queue object. Then you call on the message queue object instead of Receive() the method BeginReceive(). BeginReceive() will return immediately and the event handler you registered will be called when a message is available for reading. In the event handler you then call EndReceive() which returns the message. When you call BeginReceive() you get an IAsyncResult handler back which you need to pass along when calling EndReceive() so the method knows which asynchronous read to finish. You can call BeginReceive() multiple times. In this case you are waiting for multiple messages and for each available message your event handler gets called. Your event handler stays active, so keeps still waiting for a message, even after calling Close() on the message queue object. This behavior is due to the fact that read and write handles to the message queues are cached for performance reasons. Set the MessageQueue.EnbaleConnectionCache property to false to disables the cache which will make sure that your event handler no longer listens for messages after you close your message queue object. Here is a code snippet for asynchronous reads:

// it is important to set this to false, otherwise the message receiver event
// handler keeps still active even after closing the message queue object
MessageQueue.EnableConnectionCache = false;
// open the selected message queue
MessageQueue MQueue = new MessageQueue(MessageQueuePath);
MQueue.MessageReadPropertyFilter.SetAll();
// the target types we have stored in the message body
((XmlMessageFormatter)MQueue.Formatter).TargetTypes = new Type[] { typeof(Order) };
// set the event handler to be called when the message has been received
MQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MessageEventHandler);
// start the receive message process; this call returns immediately
IAsyncResult MQResult = MQueue.BeginReceive(new TimeSpan(1, 0, 0), MQueue);
 
/// <summary>
/// event handler called when the message is ready to be read
/// </summary>
private void MessageEventHandler(object sender, ReceiveCompletedEventArgs e){
    // get the message from the queue
    System.Messaging.Message Msg = ((MessageQueue)e.AsyncResult.AsyncState).EndReceive(e.AsyncResult);
    // process the order
    Order Order = (Order)Msg.Body;
    // start looking for the next message
    IAsyncResult AsyncResult = ((MessageQueue)e.AsyncResult.AsyncState).BeginReceive(new TimeSpan(1, 0, 0), ((MessageQueue)e.AsyncResult.AsyncState));
}

When you call BeginReceive() you can also pass along some state information. This can be any object and in our code snippet above it is the message queue object. This way the event handler can get hold of the message queue object and then call EndReceive(). If you want to continue waiting for the next message then you need to call in the event handler again BeginReceive() on the same message queue object. BeginReceive() and Receive() always read the first message in the queue and remove it from the queue. You can use Peek() and BeginPeek() with EndPeek() to peek for the first message without removing it. MessageQueue.GetAllMessages() returns you a list of all messages in a queue without removing them from the queue. Here is a code snippet:

// open the message queue
MessageQueue MQueue = new MessageQueue(MessageQueuePath);
// set the properties we want to retrieve
MQueue.MessageReadPropertyFilter.Id = true;
MQueue.MessageReadPropertyFilter.Priority = true;
MQueue.MessageReadPropertyFilter.SentTime = true;
MQueue.MessageReadPropertyFilter.MessageType = true;
MQueue.MessageReadPropertyFilter.Label = true;
// get all the messages; does not remove the messages!
Message[] Msg = MQueue.GetAllMessages();
// create a string array to store the message information
string[,] Messages = new string[Msg.Length,5];
// loop through each message and get the info we need
for (int Count = 0; Count < Msg.Length; Count++)
{
    Messages[Count, 0] = Msg[Count].Id;
    Messages[Count, 1] = Msg[Count].Label;
    Messages[Count, 2] = Msg[Count].MessageType.ToString();
    Messages[Count, 3] = Msg[Count].Priority.ToString();
    Messages[Count, 4] = Msg[Count].SentTime.ToString();
}// close the message queue
MQueue.Close();

Another way to obtain the list of messages without removing them from a queue is the method MessageQueue.GetMessageEnumerator(). It returns a MessageEnumerator enumerator which you use to move from message to message. If there is no message available it will wait the specified time span. Here is the code snippet:

// open the message queue
MessageQueue MQueue = new MessageQueue(MessageQueuePath);
// we want to retrieve all properties for the message
MQueue.MessageReadPropertyFilter.SetAll();
// get a message enumerator we can use to go through all the messages
MessageEnumerator Enumerator = MQueue.GetMessageEnumerator();
// loop through all the messages
while (Enumerator.MoveNext(new TimeSpan(0,0,1)))
{
    // get a reference to the current message
    Message Msg = Enumerator.Current;
}
// close the message queue
MQueue.Close();

The MessageQueue object provides you with a lot of control how to read and send messages. But sometimes it would be useful to get notified when a message has been sent to a queue. You can achieve that by having a windows service running in the background and receiving or peeking synchronously or asynchronously messages. There is another approach you can use, MSMQ triggers.

A closer look at MSMQ Triggers

To be able to use triggers you need to install the «Triggers» component of MSMQ and make sure that the «Message Queuing Triggers» windows service is running. You can create triggers through the «Computer Management», under the item «Services and Applications», «Message Queuing» and «Triggers». First you need to create a rule under the item «Rules». A rule specifies a condition and the action to take when that condition is met. If you don’t specify a condition, then the action applies to all messages in a queue. Otherwise the action only applies to messages which meet the condition. You can create complex conditions like the message label needs to contain this string, needs to have this priority, etc. The action can be to invoke this COM object or run this executable.

So right click on the item «Rules» and select «New | Rule» from the popup menu. Give the rule a name and description and click next. On the next screen you define the condition. Select from the drop down box the condition, for example «Message Label contains» and enter in the «filter/value» box the value of that condition, for example the string the label needs to contain. Click on the add button to add the condition. You can add as many conditions as needed or you remove individual conditions with the «Remove» button. When the condition is built, or if you don’t want to apply a condition, click on the Next button. The next screen defines the action to take when the condition is met. Select if you want to invoke a COM component or an executable. For the COM component you need to specify the ProgID and the method to be executed, for example the ProgID «MQProcessor.MessageQueueProcessor» and the method name «ProcessMessage». For an external executable to run you specify the full path and name of the EXE. With the Parameters button you add the information which gets passed on to the COM object or executable. Select the available parameter from the drop down box and click add. You can add multiple parameters, remove parameters and sort them with the up and down button. The list of parameters and their types must match your method signature if you use a COM object. For an executable this is the list of command line arguments passed along. When done click ok and ok again to save the rule. You can create as many rules as required and edit existing rules by double clicking on a rule or remove rules by right clicking on a rule and selecting «Delete» from the popup menu.

A rule does not specify to which queue it applies. That is done by creating a trigger. Under each queue you find an item called Trigger which allows you to specify a trigger for that queue. Under the item «Triggers» (under «Message Queuing») you see all triggers created on this MSMQ instance. Either way you create a new trigger by right clicking on the item «Triggers» and selecting «New | Trigger» from the popup menu. Give the trigger a name and select the processing type which can be either «Peeking», «Retrieval» or «Transactional retrieval». If you want this trigger to be active then check the «Enabled» checkbox». The «Serialized» checkbox results in a serialized processing, meaning messages are processed one by one in the order they arrive. Otherwise if multiple messages arrive at the same time multiple instances of your COM object or executable could be invoked. On the next screen, after clicking Next, you can select the rules which are associated with this trigger. The list on the left side shows the available rules. Through the attach button you can assign rules to this trigger (shown on the right side). Through the Detach button you can remove rules from this trigger. Through the Up and Down button you can order the rules. The rules are executed one by one in the order specified. Click Finish to save the trigger. You can create as many triggers as required and edit existing triggers by double clicking on a trigger or remove triggers by right clicking on a trigger and selecting «Delete» from the popup menu.

If you want to use a .NET type instead of a COM object, make sure that you assign to your type the Guid attribute and the ComVisible attribute. The message body passed along (when selected in the parameter list) is an array of bytes. In order to be able to read the object you have stored in the message body you need to create a Message object, create a MemoryStream using this array of bytes and then assign the memory stream to the BodyStream property of the message object. You need to set again the formatter to use through the Formatter property of the message object and if you use the XmlMessageFormatter you need to set again the type. Here is a code snippet:

[ComVisible(true)]
[Guid("CBA5E590-86F8-4e65-8D8D-F03E2DAD6461")]
public class MessageQueueProcessor
{
    [ComVisible(true)]
    public void ProcessMessage(object MsgBody,string MQPath,string RespFormatName)
    {
        try
        {
            // get the response message queue path from the response format name
            string MQResponsePath = RespFormatName.Split(':')[1];
            // open the respone message queue
            MessageQueue MQueue = new MessageQueue(MQResponsePath);
            // create a message out of the message body we got passed along
            // so we can read the message body in the format originally sent
            Message Msg = new Message();
            Msg.BodyStream = new System.IO.MemoryStream((Byte[])MessageBody);
            Msg.Formatter = new XmlMessageFormatter(new Type[] { typeof(Order) });
            // gets the Order from the message body passed along
            Order TheOrder = (Order)Msg.Body;
            // send the order unprocessed to the response message queue
            // specified by the received message (so by the message sender)
            MQueue.Send(TheOrder);
            // close the response message queue again
            MQueue.Close();
        }
        // catch any exception to keep the MSMQ trigger service ok
        catch(Exception)
        {}
    }
}

It is important to handle all exceptions. Any unhandled exception will result in the «Message Queuing Triggers» windows service to terminate. If your method signature does not match the parameter list specified in the rule/trigger then you will see an entry in the application event log. The source is set to «MSMQ Triggers» and the description will say that the action defined by the rule has not been invoked because the COM object is not registered. The message is a bit misleading. After you created your .NET type you need to register it as COM object using the «regasm» utility. So the type can be found and loaded you also need to install the .NET type in the GAC using the «gacutil» utility. As you develop and troubleshoot your .NET type it is best to first stop the «Message Queuing Triggers» service, then unregister the type as COM object and then to remove it from the GAC. Then register the type again as COM object, add it again to the GAC and finally start the «Message Queuing Triggers» service again. Without that sequence I encountered sometimes unexpected behaviors which cost me much time trying to debug my code without really having any issues. Create a batch file which you just run each time when you are ready to test and troubleshoot your .NET type. Here is an example:

net stop «Message Queuing Triggers»
regasm MessageQueueProcessor.dll /unregister
gacutil /u MessageQueueProcessor

regasm MessageQueueProcessor.dll
gacutil /i MessageQueueProcessor.dll
net start «Message Queuing Triggers»

If you need to debug your component, then attach the .NET debugger (through the menu «Debug | Attach to Process») to the process «mqtgsvc.exe». But only do it after you ran your component once so it recognizes the process also as .NET process. Otherwise it will not recognize your .NET component and you can’t debug it.

Summary

Microsoft Message Queue server provides a powerful messaging framework. It takes care of the complexities of guaranteed message delivery and routing. It is a great enabler to separate the parts of your application which interact with the user and back-end processing. It can also be a great enabler for asynchronous processing of long running tasks or processes. MSMQ triggers are a very convenient way to get notified about new messages and to process them. The .NET framework has a comprehensive set of types to interact with MSMQ. It makes it very easy to send and receive messages, to create new and maintain existing queues and allows to add effortlessly transactional support.

The attached sample application (created in Visual Studio 2005, using MSMQ 3.0) shows how to send transactional and non-transaction messages. It also demonstrates how to synchronously or asynchronously receive messages and how to process these messages. The interface of the example is very simplistic but it provides a framework for an administrative interface. You can create new queues, view the list of existing queues, view the properties of existing queues and view all the messages of queues. It also provides a trigger component which you can use to process incoming messages. See the «readme.htm» file for more details.

Аннотация: Рассматривается система фирмы Microsoft для обмена сообщениями между программами. Приводятся примеры применения среды MSMQ при использовании .NET Framework 2.0. Даются рекомендации по использованию систем обмена сообщениями в распределенных системах.

5.1. Служба обмена сообщениями MSMQ

В настоящий момент существует несколько основных разработок в области
промежуточного программного обеспечения для работы с очередями сообщений.
Наиболее известными разработками являются такие системы очередей сообщений, как
MSMQ, Sun Java System Message Queue, IBM MQSeries, Oracle Advanced Queing.
Промежуточная среда MSMQ – разработка Microsoft для асинхронной передачи
сообщений внутри локальной сети, впервые появившаяся в составе операционной
системы Windows NT. В настоящее время последней является версия MSMQ 3.0,
включенная в Windows XP PE и 2003 Server, достаточно актуальна так же версия 2.0,
включенная в состав операционной системы Windows 2000.

Служба MSMQ позволяет произвольному набору приложений добавлять
сообщения в некоторую очередь, и произвольному же набору – читать сообщения из
очереди. Приложению, использующему MSMQ, доступны следующие основные
операции:

  • добавить сообщение в очередь;
  • извлечь первое сообщение из очереди;
  • установить обработчик, вызываемый при появлении сообщения.

Структура сообщения определяется приложением, и может быть произвольной, с
ограничением на размер одного сообщения (2Мб для MSMQ 2.0). Далее будет
рассмотрено использование MSMQ 2.0/3.0 при разработке приложений с
использованием .NET Framework.

При отправке сообщения с использованием MSMQ посылающему приложению
необходимо указать имя компьютера и очереди, в которую его необходимо доставить.
После вызова приложением функции отправки сообщение сохраняется в локальной
исходящей очереди. Затем MSMQ определяет имя компьютера и очереди, куда
необходимо передать сообщение. Возможны следующие случаи:

  • сообщение доставляется сразу в указанную отправителем очередь (прямая доставка);
  • сообщение посылается в некоторую промежуточную очередь,
    определяемую маршрутизатором службы сообщений;
  • MSMQ определяет, что сообщение требуется разослать в несколько очередей
    (возможность поддерживается начиная с MSMQ 3.0).

Пересылка сообщения в промежуточной среде MSMQ

Рис.
5.1.
Пересылка сообщения в промежуточной среде MSMQ

После определения имени компьютера с очередью назначения, MSMQ проверяет
доступность компьютера (пакетом UDP) и в случае ответа сразу пытается отправить
ему сообщение, повторяя попытки с интервалом по умолчанию 5 секунд. Если
сообщение не удается отправить, то обычно каждые 5 минут служба сообщений
пытается найти новый пункт назначения сообщения, используя маршрутизацию
MSMQ. Процесс пересылки сообщения между компьютерами повторяется, пока оно не
достигнет очереди назначения. С момента поступления сообщения в указанную при
отправке очередь любое использующее MSMQ приложение с необходимыми правами
доступа может прочитать это сообщение (рис. 5.1).

Таким образом, MSMQ поддерживает асинхронную передачу сообщений, при
которой участвующие в обмене компоненты распределенной системы не обязательно
должны функционировать в один и тот же момент времени.

Благодаря службе маршрутизации сообщений возможно создание моста между
MSMQ и аналогичной технологией IBMIBM Websphere MQ (ранее MQSeries).
Websphere MQ может использоваться и напрямую программами .NET Framework,
однако обычно это менее удобно, чем использование MSMQ, и может быть связано с
дополнительными затратами – служба MSMQ уже входит в большинство систем
семейства Windows. Использование моста MSMQ-MQSeries позволяет создавать
гетерогенные распределенные системы на основе обмена сообщениями, поскольку
технология IBM MQ является изначально межплатформенной.

Приложение может вести поиск нужной ему очереди по ряду критериев. Это
возможно при использовании механизма общих очередей в Microsoft Message Queuing,
что требует развертывания Microsoft Active Directory.

5.2. Инфраструктура, необходимая для использования MSMQ

Служба MSMQ может работать как в составе домена Active Directory, так и при отсутствии такого домена, но во втором случае невозможно использовать ряд возможностей MSMQ, а именно:

  • не поддерживается шифрование передаваемых сообщений;
  • не поддерживаются общие очереди и механизмы их обнаружения;
  • не поддерживается маршрутизация сообщений и групповая рассылка сообщений.

В MSMQ существуют два вида очередей – общие (public) и частные (private). Как
частные, так и общие очереди могут либо использовать, либо не использовать
транзакции, что задается при создании очереди и не может быть изменено в дальнейшем.

Информация об общих очередях публикуется в службе каталогов Active Directory.
Путь к общей очереди имеет вид ComputerName\QueueName, возможна также запись
пути в виде .\QueueName для очереди на локальном компьютере. Посылающее
сообщение приложение может искать доступные в домене общие очереди по заданным
критериям. Возможна также проверка приложением наличия общей очереди на
удаленном компьютере и ее создание. Для использования общих очередей требуется
развертывание MSMQ в рамках домена Active Directory.

Частные очереди доступны как при наличии домена, так и при его отсутствии. Путь
к такой очереди имеет вид ComputerName\Private$\QueueName или .\Private$\QueueName для локального компьютера. Приложение, не
имеет возможности ни создать, ни проверить наличие частной очереди на удаленном
компьютере при использовании средств библиотеки FCL.

В MSMQ 3.0 появилась возможность посылать сообщения в общую или частную
очередь по протоколу HTTP при наличии на удаленном компьютере службы Internet
Information Services (IIS). В этом случае используется путь к очереди вида
http://domain.name/msmq/private$/queuename.
Посылающий сообщения компьютер так же должен поддерживать HTTP для MSMQ, иначе он не сможет
получать какие-либо ответы. При чтении сообщений использовать HTTP-формат имени
очереди невозможно.

MSMQ поддерживает два вида имени очереди – прямой вид ( direct name ) и путь к
очереди ( path name ). При использовании частных очередей на удаленном компьютере
обычно необходимо использовать прямой путь к очереди. При использовании MSMQ
программами на .NET Framework прямой путь записывается следующим образом:

  • Formatname:DIRECT=OS:server01\QueueName – прямое имя общей очереди на компьютере server01;
  • Formatname:DIRECT=OS:ws02\Private$\QueueName
    прямое имя частной очереди на компьютере ws02;
  • Formatname:DIRECT=TCP:192.168.30.1\private$\QueueName
    прямое имя частной очереди на компьютере с адресом 192.168.30.1.

Полноценная работа с очередями возможна только в пределах локальной или
виртуально частной сети, поскольку при чтении сообщений используется Windows RPC
(в частности, обращения на 135-й порт). Кроме этого, среда MSMQ не способна
функционировать при использовании NAT, за исключением случая HTTP-имени очереди.

Понравилась статья? Поделить с друзьями:
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
  • Как разрешить игре использовать микрофон windows 10
  • Расширение кодек hevc для windows 10
  • Подключение через удаленный помощник windows
  • Что такое searchapp exe в windows 10
  • Install snmp on windows server 2003