MSMQ in .NET

To make these systems more useful, the systems need to communicate with each other. The basic unit of data that is exchanged between software systems or different components of a multi-tier system is known as message. Message can very simple, consisting of just a few letters, or very complex, including embedded objects.

The process of sending and receiving messages is known as messaging. The technology that provides messaging facilities to any communicating application is known as MessageQueue technology. It provides the framework and makes messaging easy and reliable. There are many commercial and non-commercial implementations of messaging middleware applications, which include Oracle Advanced Queuing (AQ), IBM’s WebSphere MQ, Web Service Message Queue (WSMQ), ActiveMQ and JBossMQ. Microsoft Windows Message Queuing (MSMQ) is the MessageQueue technology from Microsoft that is supported on Windows XP and Windows NT/2000 with Option Pack 4+.

In message queuing, messages are sent to a message queue, which acts like a middleman between the sender and recipient. If the recipient is not available, it holds the messages till they are delivered successfully. The message queue guarantees delivery of messages and also provides routing facilities.

A message queue is a first in, first out data structure. A message is enqueued, placed on the end of the queue by the sender. Then the recipient de-queues the message that is retrieved and removes the message from the front end of the queue.

Message queues under the Windows operating systems are divided mainly under two categories – User-created queues and System queues.

User-created queues

These are of two types:

·  Public queues: These are replicated throughout the Message Queuing network and can potentially be accessed by any computer on the network; and
· Private queues: Private queues have all the features of public queues except that private queues are not listed in the Active Directory. Private queues can be accessed only by applications that know the full path name of the queue. Private queues are also a bit faster than public queues.

System queues
These are mainly used for administrative purposes.

Installing MSMQ on Windows XP
· Double-click on Add/Remove Programs icon in the control panel;
· Click on Add/Remove Windows Components;
· Windows Components Wizard gets displayed (figure 1). Here, check the Message Queuing item and click on Next; and
· Click on Finish to complete the installation.




Fig. 1

To verify that the Message Queuing service has been installed properly, double-click on Administrative tools in the control panel. Double-click the Services Icon and look for Message Queuing item in the Services list. Refer
figure 2.



Fig. 2


Programming MSMQ in VB.NET

In .NET, System.Messaging namespace provides a set of classes that can be used to work with MSMQ. Here, we will focus mainly on two of the most important classes in this namespace – Message and MessageQueue class. MessageQueue class provides functionality to manage MessageQueues while Message class is used to create messages that are passed between applications.

Let us create a sample application to start coding for MSMQ. The application will do the following:
· List all the private MessageQueues on the local machine;
· Add and delete MessageQueues programmatically;
· Send messages to the MessageQueue;
· Retrieve messages from the MessageQueue; and 
· Finally delete all messages from the MessageQueue.

Open Visual Studio and create a new Windows project in VB.NET. Let us name this project as MSMQApp. Visual Studio will automatically add a windows form to your project. Change the title of the form to MSMQ and add the following controls
(figure 3):


Fig. 3

Create the following sub-procedure in the form (code 1):

Code 1


Private
Sub RefreshList()
        'get the list of all private MessageQueues
        Dim mqs() As MessageQueue = MessageQueue.GetPrivateQueuesByMachine(".")
        'clear the list
        lstServices.Items.Clear()
        'add the MessageQueues retrieved
        For Each mq As MessageQueue In mqs
            lstServices.Items.Add(mq.QueueName)
        Next
End Sub

This procedure retrieves all the private MessageQueues from the local machine. Firstly, we create an array of MessageQueue objects. Next, we use GetPrivateQueuesByMachine method of the MessageQueue class to get the list of all private MessageQueues on the machine. We then clear all items in the list box and add the names of the private MessageQueues returned by GetPrivateQueuesByMachine method.

Now double-click on ‘Refresh MessageQueue List’ button (btnRefresh) to open its Click event. Add a procedure call of the sub-procedure created above. See code 2.

Code 2

 

Private Sub btnRefresh_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRefresh.Click

 

   'calls the sub-procedure that refreshes the MessageQueue list
        RefreshList()
End Sub

Now repeat the same in the Load event of the form, so that the list is refreshed automatically when the form gets loaded. Check out code 3.

Code 3

Private Sub frmMSMQ_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load
        'refresh MessageQueue list when the form loads
        RefreshList()
End Sub

Now go the design mode and double-click the Add (btnAdd) button to open its Click event. Add code 4 in it.

Code 4

Private
Sub btnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAdd.Click
        'create the path for new MessageQueue
        Dim Queue As String = ".\Private$\" & txtName.Text.Trim
         'make sure that MessageQueue has not already been created
        If Not MessageQueue.Exists(Queue) Then
            'create MessageQueue
            Dim mq As MessageQueue = MessageQueue.Create(Queue, True)
            'refresh list
            RefreshList()
        End If
End Sub

In this event, we create a new MessageQueue. Firstly, we make the path of the new MessageQueue to be created. The name of the new MessageQueue is typed by the user in the textbox and is preceded with the ".\Private$\", where "." stands for the local machine. Before creating the MessageQueue, we make sure that the MessageQueue does not already exist using the ‘Exists’ method of MessageQueue class, which returns 'True' if the MessageQueue already exists. Now, in the Click event of the Delete (btnDelete) button, add code 5.

Code 5

Private Sub btnDelete_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDelete.Click
        'make sure user has selected the MessageQueue to delete
        If lstServices.SelectedItems.Count > 0 Then
            'delete MessageQueue
            MessageQueue.Delete(".\" & lstServices.GetItemText(lstServices.SelectedItem))
            'refresh list
            RefreshList()
        End If
End Sub

We now make sure that the user has selected a MessageQueue and then we delete it. Next, in code view go to the Click event of the Send Message (btnSend) button and write the following code snippet (code 6) in it.

Code 6

Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click
        'make sure that the user has selected the MessageQueue to which messages will be enqueued
        If lstServices.SelectedItems.Count > 0 Then
            Try
                'open the MessageQueue
                Dim mq As New MessageQueue(".\" & lstServices.GetItemText(lstServices.SelectedItem))
                mq.Formatter = New BinaryMessageFormatter
                Dim msg As New Message
                'set values to the message items
                With msg
                    .Priority = MessagePriority.Low
                    .Label = txtSubject.Text.Trim
                    .Body = txtBody.Text.Trim
                End With
                'send the message and close MessageQueue
                mq.Send(msg)
                mq.Close()
                MessageBox.Show("Message send successfully!", "MSMQ", MessageBoxButtons.OK)
            Catch ex As Exception
                MessageBox.Show("Problem encountered while sending Message.", "MSMQ", MessageBoxButtons.OK)
            End Try
        End If
End Sub

Here we make sure that the user has selected the MessageQueue to which he would like to enqueue his/her messages. Then, based on the MessageQueue selected, we make the path of MessageQueue and create its object.

We set the Formatter property of the MessageQueue object to BinaryMessageFormatter. The Formatter produces a stream to be written to a message body. There are three types of Formatters that can be used with MessageQueues. Namely,
· ActiveXMessageFormatter (Used with COM components);
· BinaryMessageFormatter (Serializes message to binary representation); and
· XMLMessageFormatter (Serializes message to XML).

After that, we create the object of Message class and set its attributes. We then use ‘Send’ method of the MessageQueue object to enqueue the message. We can also directly pass the string object to the Send method, in which case the MessageQueue object will implicitly convert String object into the Message object. In the Click event of the Retrieve (btnRetrieve) button, incorporate code 7.

Code 7

 

Private Sub btnRetrieve_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRetrieve.Click
        'make sure that the user has selected the MessageQueue from which messages will be retrieved
        If lstServices.SelectedItems.Count > 0 Then
            Try
                'open the MessageQueue
                Dim mq As New MessageQueue(".\" & lstServices.GetItemText(lstServices.SelectedItem))
                mq.Formatter = New BinaryMessageFormatter
                'get all the messages
                Dim msgs() As Message = mq.GetAllMessages
                'clear the list
                lstMessages.Items.Clear()
                'all messages to the list
                For Each msg As Message In msgs
                    lstMessages.Items.Add(msg.Label & ": " & Convert.ToString(msg.Body))
                Next
                'close the MessageQueue
                mq.Close()
            Catch ex As Exception
                MessageBox.Show("Problem encountered while retrieving Messages.", "MSMQ", MessageBoxButtons.OK)
            End Try
        End If
End Sub

 

After checking that the user has selected the MessageQueue, we create its object and use its GetAllMessages method to get all the messages in the queue. This method returns the array of Message objects. We then loop through the array of Message objects. Concatenate the Label and Body of each Message object to add them in the messages list after clearing the same. Note that GetAllMessages method of the MessageQueue object does not delete messages from the queue.

Finally, in the Click event of Delete Messages, we add code 8 to delete all messages in the selected MessageQueue.

Code 8

Private Sub btnDeleteMsgs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDeleteMsgs.Click
        'make sure that the user has selected the MessageQueue from which messages will be deleted
        If lstServices.SelectedItems.Count > 0 Then
            Try
                'open the MessageQueue
                Dim mq As New MessageQueue(".\" & lstServices.GetItemText(lstServices.SelectedItem))
                'delete all messages and close MessageQueue
                mq.Purge()
                mq.Close()
                MessageBox.Show("All Messages deleted successfully!", "MSMQ", MessageBoxButtons.OK)
            Catch ex As Exception
                MessageBox.Show("Problem encountered while deleting Messages.", "MSMQ", MessageBoxButtons.OK)
            End Try
End If

Run this application and see how it works!


Fig. 4

We typed MailQueue in the textbox and clicked on the ‘Add’ button. Refer figure 4. The application added the mailqueue MessageQueue to the system under private MessageQueues. Notice that although we typed the name of the MessageQueue in pascal casing, it is automatically converted into lower case, which means that the name of the MessageQueue is always in the lower case.

Now select the MessageQueue just created and type some text in the Subject and Body textboxes. Click on the Send Message (btnSend) button and it will enqueue the message in the mailqueue MessageQueue and the user will be prompted with the MessageBox as shown in figure 5.


Fig. 5

Now click on the Retrieve Messages (btnRetrieve) button and the message that we enqueued in the mailqueue MessageQueue will be retrieved in the messages list box. Next, click on the Delete Messages (btnDeleteMsgs) button. It will delete all messages in the queue and the user will be informed via the MessageBox. See figure 6.


Fig. 6

Now again click on the Retrieve Messages (btnRetrieve) button. You will see that it brings up nothing in the messages list box as it deleted all messages in the queue when we clicked on the Delete Messages (btnDeleteMsgs) button. Similarly, we can manage public MessageQueues and build robust enterprise level applications that communicate using guaranteed message delivery systems.

The author is a developer with BQE Software Inc. His e-mail id is: sajad@programmer.net.



Added on September 6, 2006 Comment

Comments

Post a comment

Your name:

Comment: