This article describes how to create a message and send it
to Microsoft Message Queue Server in a Windows application. This article also
describes how to read from a private queue and to deserialize the message
contents for display.
Requirements
The following list outlines the recommended hardware, software, network infrastructure, and service packs that you need:
- Windows 2000 Professional (or Server), or Windows XP
Professional (or Server), with Microsoft Message Queue Server installed.
Microsoft Message Queue Server is included as an option on the four operating
systems.
This article assumes that you are familiar with the following topics:
- Microsoft Message Queue
Server
- The use of tools from the command
prompt
Writing to and reading from Microsoft Message Queue Server
The
System.Messaging namespaces in the Microsoft .NET Framework have the classes that
are required to read from and write to Microsoft Message Queue Server. Follow
these steps to create a small Windows application that mimics an online bill
payment system:
- Start Microsoft Visual Studio 2005 or Microsoft Visual Studio .NET.
- Create a new Windows application in Visual Basic 2005 or in Visual Basic .NET, and
then name it MSMQ.
- If the the Solution Explorer is not displayed, press
CTRL+ALT+L to display it.
- In the Solution Explorer, right-click References, and then select Add Reference. On the .NET tab, find the System.Message.dll file in the list of .dll files.
Click Select to select the file, and then click OK.
Note In Visual Studio 2005, you do not have to click Select. - Form1.vb now is open in Design view. If it is not open, double-click Form1.vb in the Solution Explorer.
- Press CTRL+ALT+X to open the toolbox. In the toolbox,
select Windows Forms. (In Visual Studio 2005, select All Windows Forms.) Select and drag the following to the middle of the form: four
rows each of a Label followed by a Textbox (positioned to the right of each label). Under these, add two Buttons. Press F4 to access the Property page for each control. Change the Text Property for the labels to the following (in order):
- Pay To:
- Your Name:
- Amount:
- Due Date:
Change the text on the first Button to Send
Payment, and then change the text on the second Button to
Process Payment. - Add two Imports statements above the class declaration to include the additional
classes that reside in the System.Messaging and System.Text namespaces. The System.Text namespace is for the use of the StringBuilder class, a new .NET Framework class that it is best to use when you
concatenate strings:
Imports System.Messaging
Imports System.Text
- This application works with a private queue that you must
first create in the Computer Management console. On the desktop, right-click My Computer, and then click Manage. Expand Services and Applications to find Message Queuing.
Note If you do not find Message Queuing, Message Queue Server is not
installed.
Right-click Private Queues, point to New, and then click Private Queue. Name the queue billpay. Leave the
Computer Management console open, because you return to it later to view
messages. Do not select the Make Queue Transactional check box. - As mentioned earlier in this article, this sample
application mimics an online bill payment service. Therefore, create a
structure that contains variables to hold the data that defines a payment:
Public Structure Payment
Public Payor As String
Public Payee As String
Public DueDate As Date
Public Amount As Integer
End Structure
- Click the Form1.vb (Design) tab above the editor window to return to Design view. Double-click the Send Payment button. The insertion point is now in the Button1_Click event handler in Form1.vb. The first task in this routine is to
set the properties of the structure to values of the form elements:
Dim myPayment As Payment
With myPayment
.Payor = TextBox1.Text
.Payee = TextBox2.Text
.Amount = CInt(TextBox3.Text)
.DueDate = CType(TextBox4.Text, Date)
End With
- Create an instance of the Message class, and then set the Body property to the payment structure:
Dim msg As Message = New Message()
msg.Body = myPayment
- To send a message to Microsoft Message Queue Server, the
last step is to create an instance of the MessageQueue class and to call the Send method, passing in the Message object. The MessageQueue class is the wrapper that manages the interaction with Microsoft
Message Queue Server.
Note the syntax
for setting the path to the private queue that you created in the Computer
Management console. Private queues take the form
machinename\Private$\queuename. Localhost machines are referenced with a . (a
dot or period).
Dim msgQ As New MessageQueue(".\Private$\billpay")
msgQ.Send(msg)
The code is now in place to send a message to Microsoft Message Queue
Server. The .NET Framework automatically serializes the message by using an
XMLMessageFormatter object, which is implicitly created when sending
messages. - Create another Button Click event handler for Button2, which receives and "processes" the
payment message that is sent in the Button1 event handler. The first line is the same as the one that you
just saw in the first event handler:
Dim msgQ As New MessageQueue(".\Private$\BillPay")
- Create an array of types to pass to the XMLMessageFormatter class. Note that this class must be explicitly created when
receiving messages. Its constructor takes either a string array of type names
or, more preferably, a Type array of types:
Dim arrTypes(1) As System.Type
arrTypes(0) = GetType(Payment)
arrTypes(1) = GetType(Object)
msgQ.Formatter = New XmlMessageFormatter(arrTypes)
Dim myPayment As Payment = CType(msgQ.Receive.Body, Payment)
These types tell the XMLMessageFormatter how to deserialize the message. - Messages are received by calling the Receive method. Access the Body property to read the message contents. This property returns an
object, so it must be cast to the payment type to retrieve the contents in a
usable form:
Dim sb As New StringBuilder()
sb.Append("Payment paid to: " & myPayment.Payor)
sb.Append(vbCrLf)
sb.Append("Paid by: " & myPayment.Payee)
sb.Append(vbCrLf)
sb.Append("Amount: $" & myPayment.Amount.ToString)
sb.Append(vbCrLf)
sb.Append("Due Date: " & myPayment.DueDate.ToShortDateString)
- Create a message box to display the results:
MessageBox.Show(sb.ToString, "Message Received!")
Complete code listing (Form1.vb)
Imports System.Messaging
Imports System.Text
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call.
End Sub
'Form overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
Friend WithEvents Button1 As System.Windows.Forms.Button
Friend WithEvents TextBox1 As System.Windows.Forms.TextBox
Friend WithEvents Button2 As System.Windows.Forms.Button
Friend WithEvents Label1 As System.Windows.Forms.Label
Friend WithEvents TextBox2 As System.Windows.Forms.TextBox
Friend WithEvents Label2 As System.Windows.Forms.Label
Friend WithEvents TextBox3 As System.Windows.Forms.TextBox
Friend WithEvents Label3 As System.Windows.Forms.Label
Friend WithEvents Label4 As System.Windows.Forms.Label
Friend WithEvents TextBox4 As System.Windows.Forms.TextBox
'Required by the Windows Form Designer.
Private components As System.ComponentModel.Container
'NOTE: The following procedure is required by the Windows Form Designer.
'It can be modified by using the Windows Form Designer.
'Do not modify it by using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
Me.Button1 = New System.Windows.Forms.Button
Me.Button2 = New System.Windows.Forms.Button
Me.TextBox1 = New System.Windows.Forms.TextBox
Me.Label1 = New System.Windows.Forms.Label
Me.TextBox2 = New System.Windows.Forms.TextBox
Me.Label2 = New System.Windows.Forms.Label
Me.TextBox3 = New System.Windows.Forms.TextBox
Me.Label3 = New System.Windows.Forms.Label
Me.Label4 = New System.Windows.Forms.Label
Me.TextBox4 = New System.Windows.Forms.TextBox
Me.SuspendLayout()
'
'Button1
'
Me.Button1.Location = New System.Drawing.Point(104, 160)
Me.Button1.Name = "Button1"
Me.Button1.Size = New System.Drawing.Size(88, 23)
Me.Button1.TabIndex = 1
Me.Button1.Text = "Send Payment"
'
'Button2
'
Me.Button2.Location = New System.Drawing.Point(96, 200)
Me.Button2.Name = "Button2"
Me.Button2.Size = New System.Drawing.Size(104, 23)
Me.Button2.TabIndex = 3
Me.Button2.Text = "Process Payment"
'
'TextBox1
'
Me.TextBox1.Location = New System.Drawing.Point(128, 46)
Me.TextBox1.Name = "TextBox1"
Me.TextBox1.TabIndex = 2
Me.TextBox1.Text = ""
'
'Label1
'
Me.Label1.Location = New System.Drawing.Point(71, 48)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(48, 23)
Me.Label1.TabIndex = 4
Me.Label1.Text = "Pay To:"
'
'TextBox2
'
Me.TextBox2.Location = New System.Drawing.Point(128, 72)
Me.TextBox2.Name = "TextBox2"
Me.TextBox2.TabIndex = 2
Me.TextBox2.Text = ""
'
'Label2
'
Me.Label2.Location = New System.Drawing.Point(52, 74)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(72, 23)
Me.Label2.TabIndex = 4
Me.Label2.Text = "Your Name:"
'
'TextBox3
'
Me.TextBox3.Location = New System.Drawing.Point(128, 96)
Me.TextBox3.Name = "TextBox3"
Me.TextBox3.TabIndex = 2
Me.TextBox3.Text = ""
'
'Label3
'
Me.Label3.Location = New System.Drawing.Point(70, 99)
Me.Label3.Name = "Label3"
Me.Label3.Size = New System.Drawing.Size(48, 23)
Me.Label3.TabIndex = 4
Me.Label3.Text = "Amount:"
'
'Label4
'
Me.Label4.Location = New System.Drawing.Point(60, 124)
Me.Label4.Name = "Label4"
Me.Label4.Size = New System.Drawing.Size(59, 23)
Me.Label4.TabIndex = 4
Me.Label4.Text = "Due Date:"
'
'TextBox4
'
Me.TextBox4.Location = New System.Drawing.Point(128, 120)
Me.TextBox4.Name = "TextBox4"
Me.TextBox4.TabIndex = 2
Me.TextBox4.Text = ""
'
'Form1
'
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.ClientSize = New System.Drawing.Size(292, 266)
Me.Controls.AddRange(New System.Windows.Forms.Control() _
{Me.Label4, Me.TextBox4, Me.TextBox3, Me.Label3, _
Me.TextBox2, Me.Label2, Me.Label1, Me.Button2, _
Me.TextBox1, Me.Button1})
Me.Name = "Form1"
Me.Text = "Form1"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
End Sub
Public Structure Payment
Public Payor As String
Public Payee As String
Public DueDate As Date
Public Amount As Integer
End Structure
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim myPayment As Payment
With myPayment
.Payor = TextBox1.Text
.Payee = TextBox2.Text
.Amount = CInt(TextBox3.Text)
.DueDate = CType(TextBox4.Text, Date)
End With
Dim msg As Message = New Message
msg.Body = myPayment
Dim msgQ As New MessageQueue(".\Private$\BillPay")
msgQ.Send(msg)
End Sub
Private Sub Button2_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button2.Click
Dim msgQ As MessageQueue = New MessageQueue(".\Private$\BillPay")
Dim arrTypes(1) As System.Type
arrTypes(0) = GetType(Payment)
arrTypes(1) = GetType(Object)
msgQ.Formatter = New XmlMessageFormatter(arrTypes)
Dim myPayment As Payment = CType(msgQ.Receive.Body, Payment)
Dim sb As New StringBuilder
sb.Append("Payment paid to: " & myPayment.Payor)
sb.Append(vbCrLf)
sb.Append("Paid by: " & myPayment.Payee)
sb.Append(vbCrLf)
sb.Append("Amount: $" & myPayment.Amount.ToString)
sb.Append(vbCrLf)
sb.Append("Due Date: " & myPayment.DueDate.ToShortDateString)
MessageBox.Show(sb.ToString, "Message Received!")
End Sub
End Class
Note
You must change the code in Visual Basic 2005. By default, Visual Basic creates two files for the project when you create a Windows Forms project. If the form is named Form1, the two files that represent the form are named Form1.vb and Form1.Designer.vb. You write the code in the Form1.vb file. The Windows Forms Designer writes the code in the Form1.Designer.vb file. The Windows Forms
Designer uses the partial keyword to divide the implementation of Form1 into two separate files. This behavior prevents the designer-generated code
from being interspersed with your code.
For more information about partial classes and the Windows Forms Designer, visit the following Microsoft Developer Network (MSDN) Web site:
Verification
- Press F5 to run the application in Debug mode.
- Type values in each TextBox, and then click Send Payment.
- Press ALT+TAB to return to the Computer Management console.
Click the Queue messages folder in Private Queues under billpay, and then verify that Microsoft Message Queue Server received a
message (indicated by an envelope icon). Right-click the message, select Properties, and then click the Body tab to check the message.
Note The contents of the payment message are serialized as
XML. - Press ALT+TAB to return to the bill payment Windows
application. Click the Process Payment button. You see a message box that confirms the receipt of a
message and displays the message text.
Troubleshooting
- Forgetting to create a private queue is usually an issue
only on Windows 2000 Professional and Windows XP Professional. Windows 2000
Server and Windows Server 2003 permit the use of the public queue.
- Passing the correct arguments to the XMLMessageFormatter()
can be tricky. In this example, exceptions are thrown if either the object or
the Payment Types are not included in the Type array that is passed to the
constructor.
REFERENCES
For more information about Microsoft Message Queue Server, visit the following Microsoft Web sites: