Jan 3, 2008

A MSMQ Listener

The 2 following classes are used to get the desired effect.
The MSMQListener Class as the name suggests is the main class, while the Form1.cs is a windows forms which invokes this class and shows a popup when a message is queued. Additionally, this form also is used to post messages to the queue

----------------------------------------------------
1. MSMQListener Class
----------------------------------------------------

using System;
using System.Collections.Generic;
using System.Text;
using System.Messaging;

namespace MyQueue
{
public delegate void MessageReceivedEventHandler(object sender, MessageEventArgs args);

public class MSMQListener
{
private bool _listen;
private Type[] _types;
private MessageQueue _queue;

public event MessageReceivedEventHandler MessageReceived;

public Type[] FormatterTypes
{
get { return _types; }
set { _types = value; }
}

public MSMQListener(string queuePath)
{
this.ConstructorCommon(queuePath);
}

public MSMQListener(string queuePath, System.Messaging.IMessageFormatter formatter)
{
this.ConstructorCommon(queuePath);
this._queue.Formatter = formatter; // Customize the formatter type
}

private void ConstructorCommon(string queuePath)
{
_queue = new MessageQueue(queuePath);
}


public void Start()
{
_listen = true;

if (_types != null && _types.Length > 0)
{
// Using only the XmlMessageFormatter. You can use other formatters as well
_queue.Formatter = new XmlMessageFormatter(_types);
}

_queue.PeekCompleted += new PeekCompletedEventHandler(OnPeekCompleted);
_queue.ReceiveCompleted += new ReceiveCompletedEventHandler(OnReceiveCompleted);

StartListening();
}

public void Stop()
{
_listen = false;
_queue.PeekCompleted -= new PeekCompletedEventHandler(OnPeekCompleted);
_queue.ReceiveCompleted -= new ReceiveCompletedEventHandler(OnReceiveCompleted);

}

private void StartListening()
{
if (!_listen)
{
return;
}

// The MSMQ class does not have a BeginRecieve method that can take in a
// MSMQ transaction object. This is a workaround - we do a BeginPeek and then
// recieve the message synchronously in a transaction.
// Check documentation for more details
if (_queue.Transactional)
{
_queue.BeginPeek();
}
else
{
_queue.BeginReceive();
}
}

private void OnPeekCompleted(object sender, PeekCompletedEventArgs e)
{
_queue.EndPeek(e.AsyncResult);
MessageQueueTransaction trans = new MessageQueueTransaction();
Message msg = null;
try
{
trans.Begin();
msg = _queue.Receive(trans);
trans.Commit();

StartListening();

FireRecieveEvent(msg.Body);
}
catch
{
trans.Abort();
}
}

private void FireRecieveEvent(object body)
{
if (MessageReceived != null)
{
MessageReceived(this, new MessageEventArgs(body));
}
}

private void OnReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
Message msg = _queue.EndReceive(e.AsyncResult);

StartListening();

FireRecieveEvent(msg.Body);
}

}

public class MessageEventArgs : EventArgs
{
private object _messageBody;

public object MessageBody
{
get { return _messageBody; }
}

public MessageEventArgs(object body)
{
_messageBody = body;

}
}
}



-----------------------------------------------------------------------------
2. Form1.cs
-----------------------------------------------------------------------------

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Messaging;
using System.Threading;

namespace MyQueue
{
///
/// Summary description for Form1.
///

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.TextBox txtMsg;
private System.Windows.Forms.Button btnMsg;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.ListBox MsgBox;
private System.Windows.Forms.Label Messages;
private System.Windows.Forms.Button btnRcv;
///
/// Required designer variable.
///

private System.ComponentModel.Container components = null;
public System.Messaging.MessageQueue mq;
public static Int32 j=0;

public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//

//Q Creation
if(MessageQueue.Exists(@".\Private$\MyQueue"))
mq = new System.Messaging.MessageQueue(@".\Private$\MyQueue");
else
mq = MessageQueue.Create(@".\Private$\MyQueue");

Queue2 q2 = new Queue2();
q2.Show();


///////
MSMQListener msmq = new MSMQListener(@".\Private$\MyQueue", new System.Messaging.XmlMessageFormatter(new string[] {"System.String"}));
msmq.MessageReceived += new MessageReceivedEventHandler(msmq_MessageReceived);
msmq.Start();
}

void msmq_MessageReceived(object sender, MessageEventArgs args)
{
MessageBox.Show(args.MessageBody.ToString());
}

///
/// Clean up any resources being used.
///

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///

private void InitializeComponent()
{
this.txtMsg = new System.Windows.Forms.TextBox();
this.btnMsg = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.MsgBox = new System.Windows.Forms.ListBox();
this.Messages = new System.Windows.Forms.Label();
this.btnRcv = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// txtMsg
//
this.txtMsg.Location = new System.Drawing.Point(112, 16);
this.txtMsg.Name = "txtMsg";
this.txtMsg.Size = new System.Drawing.Size(280, 20);
this.txtMsg.TabIndex = 0;
this.txtMsg.Text = "";
//
// btnMsg
//
this.btnMsg.Location = new System.Drawing.Point(200, 48);
this.btnMsg.Name = "btnMsg";
this.btnMsg.TabIndex = 1;
this.btnMsg.Text = "&Send";
this.btnMsg.Click += new System.EventHandler(this.btnMsg_Click);
//
// label1
//
this.label1.Location = new System.Drawing.Point(8, 16);
this.label1.Name = "label1";
this.label1.TabIndex = 4;
this.label1.Text = "Enter Message :";
//
// MsgBox
//
this.MsgBox.Location = new System.Drawing.Point(8, 136);
this.MsgBox.Name = "MsgBox";
this.MsgBox.Size = new System.Drawing.Size(392, 173);
this.MsgBox.TabIndex = 2;
//
// Messages
//
this.Messages.Location = new System.Drawing.Point(16, 104);
this.Messages.Name = "Messages";
this.Messages.Size = new System.Drawing.Size(160, 23);
this.Messages.TabIndex = 3;
this.Messages.Text = "Messages : ";
//
// btnRcv
//
this.btnRcv.Location = new System.Drawing.Point(200, 88);
this.btnRcv.Name = "btnRcv";
this.btnRcv.TabIndex = 5;
this.btnRcv.Text = "&Receive";
this.btnRcv.Click += new System.EventHandler(this.btnRcv_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(408, 317);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.btnRcv,
this.Messages,
this.MsgBox,
this.label1,
this.btnMsg,
this.txtMsg});
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Queue1";
this.ResumeLayout(false);

}
#endregion

///
/// The main entry point for the application.
///

[STAThread]
static void Main()
{
Application.Run(new Form1());
}

private void btnMsg_Click(object sender, System.EventArgs e)
{
// SendMessage(Handle, 1, 0, IntPtr.Zero);
System.Messaging.Message mm = new System.Messaging.Message();
mm.Body = txtMsg.Text;
mm.Label = "Msg" + j.ToString();
j++;
mq.Send(mm);
}

private void btnRcv_Click(object sender, System.EventArgs e)
{
System.Messaging.Message mes;
string m;

try
{
mes = mq.Receive(new TimeSpan(0, 0, 3));
mes.Formatter = new XmlMessageFormatter(new String[] {"System.String,mscorlib"});
m = mes.Body.ToString();
}
catch
{
m = "No Message";
}
MsgBox.Items.Add(m.ToString());
}
}
}

-----------------------------------------------------------------------------