How to write to and read from Microsoft Message Queuing in Visual C++ .NET or in Visual C++ 2005 (815809)
The information in this article applies to:
- Microsoft .NET Framework 1.0
- Microsoft .NET Framework 1.1
- Microsoft Message Queue Server (MSMQ) 1.0
- the operating system: Microsoft Windows 2000
- the operating system: Microsoft Windows XP
- the operating system: Microsoft Windows Server 2003
- Microsoft Visual C++ 2005 Express Edition
- Microsoft Visual C++ .NET (2003)
For a Microsoft Visual C# .NET version of this
article, see
815811. For a Microsoft Visual Basic .NET version of this
article, see
315698. This article references the following
Microsoft .NET Framework Class Library namespaces:
- System::Messaging
- System::Text
- System::Collections
IN THIS TASKSUMMARYThis article describes how to create a message and send the
message to Microsoft Message Queuing in a Windows application. This article
also describes how to read from a private queue and how to deserialize the
message contents for display. back to
the topRequirements The
following list outlines the recommended hardware, software, network
infrastructure, and service packs that you need:One of the
following operating systems with Message Queuing installed (Message Queuing is
included with the operating systems as an option):
- Microsoft Windows 2000 Professional or Microsoft Windows
2000 Server
- Microsoft Windows XP Professional
- Microsoft Windows Server 2003
This
article assumes that you are familiar with the following topics:
- Microsoft Message Queuing
- Using tools from the command prompt
back to the
topWrite to and Read from Message QueuingThe System.Messaging namespace in the .NET Framework has the classes that you must
read from and write to Message Queuing. To create a small Windows application
that mimics an online bill payment system, follow these steps:
- Start Microsoft Visual Studio .NET or Microsoft Visual
Studio 2005.
- On the File menu, point to
New, and then click Project.
- Click Visual C++ Projects under
Project Types, and then click Windows Form
Application under Templates.
Note In Visual Studio 2005, click Visual C++ under
Project Types, and then click Windows Form
Application under Templates. - Name the project MSMQ.
- In Solution Explorer, right-click
References, and then click Add
Reference.
Note In Solution Explorer, right-click MSMQ, click
References, and then click Add New
Reference. - On the .NET tab, click
System.Messaging.dll file from the list of .dll files. Click
Select, and then click OK.
- In Solution Explorer, double-click
Form1.h(design).
- Press the CTRL+ALT+X key combination to open the toolbox.
Click the Windows Forms tab.
- Add the following to the middle of Form1.h (design):
- 4 rows each of a Label and a
Textbox (positioned to the right of each label).
- Under the labels and text boxes, add two
Button controls to Form1.h (design).
- Right-click the controls, click
Properties, and then set the Text property
for the labels to the following (in order):
- Pay To:
- Your Name:
- Amount:
- Due Date:
- In the Properties dialog box, set the
Text property of the button1 control to
Send Payment, and then set the Text
property of the button2 control to Process
Payment.
- This application works with a private queue that you must
first create in the Computer Management console. To do this, follow these
steps:
- On the desktop, right-click My
Computer, and then click Manage.
- Expand Services and Applications to
find Message Queuing.
Note You may not find the Messaging Queuing, when it is not installed.
- Expand Message Queuing, right-click
Private Queues, point to New, and then click
Private Queue.
- In the Queue name text box, type
billpay, and then click OK.
Note Click to clear the Transactional check box.
Leave the Computer Management console open for viewing messages.
- At the top of the code in the Form1.h file, add two USING
NAMESPACE statements before the class declaration to include the additional
classes that reside in the System::Messaging namespace and the System::Text namespace. (The StringBuilder class, a new .NET Framework class that it is best to use when you
concatenate strings, uses the System.Text namespace.)
using namespace System::Messaging;
using namespace System::Text;
- Create a structure that contains variables to hold the data
that defines a payment. To create the structure, add the following code above
the declaration of the Form1 class::
__gc public struct Payment
{
System::String __gc* Payor;
System::String __gc* Payee;
int Amount;
System::String __gc* DueDate;
}; - Add the code in the following steps to the
Click event of button1:
- Set the properties of the structure to values of the
form elements as follows:
Payment* myPayment = new Payment;
myPayment->Payor = textBox1->Text;
myPayment->Payee = textBox2->Text;
myPayment->Amount = Convert::ToInt32(textBox3->Text);
myPayment->DueDate = textBox4->Text; - Create an instance of the Message class, and then set the Body property to the payment structure:
System::Messaging::Message *msg = new System::Messaging::Message();
msg->Body=myPayment; - To send a message to Message Queuing, create an
instance of the MessageQueue class and call the Send method that passes in the Message object. The MessageQueue class is the wrapper that manages the interaction with Message
Queuing.
Notice the syntax for setting the path of the private queue
that you created in the Computer Management console. Private queues take the
following form:computername\Private$\queuename Local host computers are referenced with a dot or a period ( ".")
as follows:MessageQueue *msgQ =new MessageQueue(S".\\Private$\\billpay");
msgQ->Send(msg); The code now exists to send a message to Microsoft Message Queuing.
The .NET Framework automatically serializes the message by using an XMLMessageFormatter object. This object is implicitly created when messages are sent.
- Add the following code to the Click event of the button2 control. The button2_Click event handler receives and processes the payment message that is
sent in the button1 event handler.
- The first line of code is the same as the line of code
that is in the first event handler:
MessageQueue *msgQ = new MessageQueue(S".\\Private$\\billpay"); - Create an array of types to pass to the XMLMessageFormatter class.
Note This class must be explicitly created when receiving messages.
The constructor of the XMLMessageFormatter class takes either a string array of type names or, more
preferably, a Type array of types: Payment *myPayment=new Payment();
Object *o=new Object();
System::Type *arrTypes[] = new System::Type* [2] ;
arrTypes[0] = myPayment->GetType();
arrTypes[1] = o->GetType();
msgQ->Formatter = new XmlMessageFormatter(arrTypes);
myPayment= static_cast<Payment*>(msgQ->Receive()->Body); 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. The Body property returns an object. Therefore, the object is cast to the
payment type to retrieve the contents in a usable form:
StringBuilder *sb = new StringBuilder();
sb->Append(S"Payment paid to: ");
sb->Append(myPayment->Payor);
sb->Append(S"\n");
sb->Append(S"Paid by: ");
sb->Append(myPayment->Payee);
sb->Append(S"\n");
sb->Append(S"Amount: $");
sb->Append(myPayment->Amount.ToString());
sb->Append(S"\n");
sb->Append(S"Due Date: ");
sb->Append(Convert::ToString(Convert::ToDateTime(myPayment->DueDate))); - Create a message box to display the results:
MessageBox::Show(sb->ToString(), S"Message Received!");
back to the
topComplete Code Listing (msmq.h)#pragma once
using namespace System::Messaging;
using namespace System::Text;
namespace MSMQ
{
using namespace System;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;
__gc public struct Payment
{
System::String __gc* Payor;
System::String __gc* Payee;
int Amount;
System::String __gc* DueDate;
};
/// <summary>
/// Summary for Form1
///
/// WARNING: If you change the name of this class, you must change the
/// 'Resource File Name' property for the managed resource compiler tool
/// that is associated with all .resx files that this class depends on. Otherwise,
/// the designers cannot interact correctly with localized
/// resources that are associated with this form.
/// </summary>
public __gc class Form1 : public System::Windows::Forms::Form
{
public:
Form1(void)
{
InitializeComponent();
}
protected:
void Dispose(Boolean disposing)
{
if (disposing && components)
{
components->Dispose();
}
__super::Dispose(disposing);
}
private: System::Windows::Forms::Label * label1;
private: System::Windows::Forms::Label * label2;
private: System::Windows::Forms::Label * label3;
private: System::Windows::Forms::Label * label4;
private: System::Windows::Forms::TextBox * textBox1;
private: System::Windows::Forms::TextBox * textBox2;
private: System::Windows::Forms::TextBox * textBox3;
private: System::Windows::Forms::TextBox * textBox4;
private: System::Windows::Forms::Button * button1;
private: System::Windows::Forms::Button * button2;
private:
/// <summary>
/// Required designer variable.
/// </summary>
System::ComponentModel::Container * components;
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
void InitializeComponent(void)
{
this->label1 = new System::Windows::Forms::Label();
this->label2 = new System::Windows::Forms::Label();
this->label3 = new System::Windows::Forms::Label();
this->label4 = new System::Windows::Forms::Label();
this->textBox1 = new System::Windows::Forms::TextBox();
this->textBox2 = new System::Windows::Forms::TextBox();
this->textBox3 = new System::Windows::Forms::TextBox();
this->textBox4 = new System::Windows::Forms::TextBox();
this->button1 = new System::Windows::Forms::Button();
this->button2 = new System::Windows::Forms::Button();
this->SuspendLayout();
//
// label1
//
this->label1->Location = System::Drawing::Point(16, 32);
this->label1->Name = S"label1";
this->label1->TabIndex = 0;
this->label1->Text = S"Pay To:";
//
// label2
//
this->label2->Location = System::Drawing::Point(16, 72);
this->label2->Name = S"label2";
this->label2->TabIndex = 1;
this->label2->Text = S"Your Name:";
//
// label3
//
this->label3->Location = System::Drawing::Point(16, 112);
this->label3->Name = S"label3";
this->label3->TabIndex = 2;
this->label3->Text = S"Amount:";
//
// label4
//
this->label4->Location = System::Drawing::Point(16, 152);
this->label4->Name = S"label4";
this->label4->TabIndex = 3;
this->label4->Text = S"Due Date:";
//
// textBox1
//
this->textBox1->Location = System::Drawing::Point(136, 32);
this->textBox1->Name = S"textBox1";
this->textBox1->TabIndex = 4;
this->textBox1->Text = S"ABC";
//
// textBox2
//
this->textBox2->Location = System::Drawing::Point(136, 72);
this->textBox2->Name = S"textBox2";
this->textBox2->TabIndex = 5;
this->textBox2->Text = S"DEF";
//
// textBox3
//
this->textBox3->Location = System::Drawing::Point(136, 112);
this->textBox3->Name = S"textBox3";
this->textBox3->TabIndex = 6;
this->textBox3->Text = S"12";
//
// textBox4
//
this->textBox4->Location = System::Drawing::Point(136, 152);
this->textBox4->Name = S"textBox4";
this->textBox4->TabIndex = 7;
this->textBox4->Text = S"9/9/2003";
//
// button1
//
this->button1->Location = System::Drawing::Point(24, 208);
this->button1->Name = S"button1";
this->button1->Size = System::Drawing::Size(88, 23);
this->button1->TabIndex = 8;
this->button1->Text = S"Send Payment";
this->button1->Click += new System::EventHandler(this, button1_Click);
//
// button2
//
this->button2->Location = System::Drawing::Point(152, 208);
this->button2->Name = S"button2";
this->button2->Size = System::Drawing::Size(104, 23);
this->button2->TabIndex = 9;
this->button2->Text = S"Process Payment";
this->button2->Click += new System::EventHandler(this, button2_Click);
//
// Form1
//
this->AutoScaleBaseSize = System::Drawing::Size(5, 13);
this->ClientSize = System::Drawing::Size(292, 266);
this->Controls->Add(this->button2);
this->Controls->Add(this->button1);
this->Controls->Add(this->textBox4);
this->Controls->Add(this->textBox3);
this->Controls->Add(this->textBox2);
this->Controls->Add(this->textBox1);
this->Controls->Add(this->label4);
this->Controls->Add(this->label3);
this->Controls->Add(this->label2);
this->Controls->Add(this->label1);
this->Name = S"Form1";
this->Text = S"Form1";
this->ResumeLayout(false);
}
private: System::Void button1_Click(System::Object * sender, System::EventArgs * e)
{
try
{
Payment* myPayment = new Payment;
myPayment->Payor = textBox1->Text;
myPayment->Payee = textBox2->Text;
myPayment->Amount = Convert::ToInt32(textBox3->Text);
myPayment->DueDate = textBox4->Text;
System::Messaging::Message *msg = new System::Messaging::Message();
msg->Body=myPayment;
MessageQueue *msgQ =new MessageQueue(S".\\Private$\\billpay");
msgQ->Send(msg);
}
catch(Exception *e)
{
MessageBox::Show(e->Message);
}
}
private: System::Void button2_Click(System::Object * sender, System::EventArgs * e)
{
try
{
MessageQueue *msgQ = new MessageQueue(S".\\Private$\\billpay");
Payment *myPayment=new Payment();
Object *o=new Object();
System::Type *arrTypes[] = new System::Type* [2] ;
arrTypes[0] = myPayment->GetType();
arrTypes[1] = o->GetType();
msgQ->Formatter = new XmlMessageFormatter(arrTypes);
myPayment= static_cast<Payment*>(msgQ->Receive()->Body);
StringBuilder *sb = new StringBuilder();
sb->Append(S"Payment paid to: ");
sb->Append(myPayment->Payor);
sb->Append(S"\n");
sb->Append(S"Paid by: ");
sb->Append(myPayment->Payee);
sb->Append(S"\n");
sb->Append(S"Amount: $");
sb->Append(myPayment->Amount.ToString());
sb->Append(S"\n");
sb->Append(S"Due Date: ");
sb->Append(Convert::ToString(Convert::ToDateTime(myPayment->DueDate)));
MessageBox::Show(sb->ToString(), S"Message Received!");
}
catch(Exception *e)
{
MessageBox::Show(e->Message);
}
}
};
}
Note You must add the common language runtime support compiler option
(/clr:oldSyntax) in Visual C++ 2005 to successfully compile the previous code
sample. To add the common language runtime support compiler option in Visual
C++ 2005, follow these steps:
- Click Project, and then click
<ProjectName>
Properties.
Note <ProjectName> is a placeholder
for the name of the project. - Expand Configuration Properties, and then
click General.
- Click to select Common Language Runtime Support,
Old Syntax (/clr:oldSyntax) in the Common Language Runtime
support project setting in the right pane, click
Apply, and then click OK.
For more information about the common language runtime support
compiler option, visit the following Microsoft Web site: back to the topVerify the Code- On the Debug menu, click
Start.
- Type values in each text box, and then click Send
Payment.
- Return to the Computer Management console. In
Private Queues under billpay, click the
Queue messages folder, and then verify that Message Queuing
received a message. An envelope icon indicates a new message.
- Right-click the message, click Properties,
and then click the Body tab. You notice the payment
message.
Note The contents of the payment message are serialized as XML.
- Return to the bill payment Windows application, and then
click Process Payment. You receive a message box that confirms
the receipt of a message and that displays the message.
back to the
topTroubleshooting- The lack of a private queue is generally an issue only on
computers that are running Windows 2000 Professional or Windows XP
Professional. Windows 2000 Server and Windows Server 2003 permit the use of the
public queue.
- Passing the correct arguments to 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.
back to the
topREFERENCESFor more information about Microsoft Message Queuing, visit
the following Microsoft Web sites: back to the
top
Modification Type: | Major | Last Reviewed: | 3/17/2006 |
---|
Keywords: | kbForms kbWindowsForms kbServer kbHOWTOmaster KB815809 kbAudDeveloper kbAudITPRO |
---|
|
|
©2004 Microsoft Corporation. All rights reserved.
|
|