Introduction
This article describes how to access the Outgoing Message Queues, and how to peek and receive messages from outgoing queues.
Background
I was asked to develop a module in which users could see their undelivered messages, i.e., those messages that were supposed to be delivered to the client but due to their unavailability (unavailability of the client's machine in the network) were sent to the outgoing queue (this is the default behaviour of the Microsoft Message Queue).
At first, I thought that it would be an easy task, but after a little research, I found out that it won't be as easy as I thought. But somehow, I managed to find the references about how to do this.
There are things that I am still unable to do, for example, I still can't delete/purge messages in the outgoing queues. I still can't get the original outgoing queue names - I now do this by selecting all the active queues in the local system and filtering out the queues that contain "private" in their name because the outgoing queues always have "Direct" in their name.
I admit that the code is a little dirty as this is a quick try to submit my first article. Hope it will be useful to my fellow C# developers.
Using the code
The code in this article is based on the COM MSMQ library. You must add a reference to the Microsoft Message Queue 3.0 Object library from the "COM" tab of the "Add Reference" window, as shown in the picture below.
The following code will return all the outgoing queue names in an ArrayList
. As I said earlier, I still can't get real outgoing queues. Here, I supposed that among all active queues, the queues containing "Direct=" in their name are the outgoing queues.
This method uses the MSMQ.MSMQApplication
COM object to get the names of all active queues; from these names, we filter out those with name containing "Direct=" as our desired queues. More information on the MSMQ.MSMQApplication
class can be found here.
private ArrayList GetOutGoingQueueName()
{
ArrayList OutgoingQueuename = new ArrayList();
try
{
MSMQ.MSMQApplication q = new MSMQ.MSMQApplication();
object obj = q.ActiveQueues;
Object[] oArray = (Object[])obj;
for (int i = 0; i < oArray.Length; i++)
{
if (oArray[i] == null)
continue;
if (oArray[i].ToString().IndexOf("DIRECT=") >= 0)
{
OutgoingQueuename.Add(oArray[i].ToString());
}
}
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
return OutgoingQueuename;
}
The next method will return the total number of messages in a queue, when the queue name is provided as the method argument.
This method uses the MSMQ.MSMQManagement
object to initialize the queue. After calling the Init
method, the object mgmt
is cast into a MSMQ.MSMQOutgoingQueueManagement
object to get the message count in the outgoing message queue. More information on MSMQ.MSMQManagement
and MSMQ.MSMQOutgoingQueueManagement
can be found here and here, respectively.
private int GetMessageCount(string queueName)
{
int count = 0;
try
{
MSMQ.MSMQManagement mgmt = new MSMQ.MSMQManagement();
MSMQ.MSMQOutgoingQueueManagement outgoing;
String s = "YOURPCNAME";
Object ss = (Object)s;
String pathName = queueName;
Object pn = (Object)pathName;
String format = null;
Object f = (Object)format;
mgmt.Init(ref ss , ref f, ref pn);
outgoing = (MSMQ.MSMQOutgoingQueueManagement)mgmt;
count = outgoing.MessageCount;
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
return count;
}
The third method "ReceiveMessage
" will return the message(s) from the queue, whose name is provided in the argument list. The other parameter defines the number of messages to read from the queue. The following method uses the MSMQ.MSMQQueueInfo
class to read messages in the outgoing queue. The Open
method of the class MSMQQueueInfo
requires two parameters. The first argument specifies how the application accesses the queue and the second argument specifies who can access the queue. More information about these parameters can be found here.
The Open
method will return a MSMQ.MSMQQueue
class object from which you can receive or peek the messages from the message queue.
More information on MSMQQueueInfo
, MSMQQueue
, and MSMQMessage
can be found here, here, and here, respectively.
private ArrayList ReceiveMessage(string queueFormatName, int numOfMessagesToRead)
{
ArrayList messages = new ArrayList();
try
{
MSMQ.MSMQQueueInfo info = new MSMQ.MSMQQueueInfo();
info.FormatName = queueFormatName;
MSMQ.MSMQQueue mq = info.Open((int)(MSMQ.MQACCESS.MQ_ADMIN_ACCESS |
MSMQ.MQACCESS.MQ_RECEIVE_ACCESS), (int)MSMQ.MQSHARE.MQ_DENY_NONE);
object wantdest = false;
object tr = true;
object num = 0;
for (int i = 0; i < numOfMessagesToRead; i++)
{
MSMQ.MSMQMessage msg = mq.ReceiveCurrent(ref wantdest,
ref wantdest, ref tr, ref num, ref wantdest);
if (msg == null)
continue;
messages.Add(System.Text.ASCIIEncoding.ASCII.GetString((byte[])msg.Body));
}
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
return messages;
}
The main difference between Peek
and Receive
is, the Peek
method just reads the message without deleting it from the queue whereas the Receive
method deletes the message after reading it from the queue.
private ArrayList PeekMessage(string queueFormatName, int numOfMessagesToRead)
{
ArrayList messages = new ArrayList();
try
{
for (int i = 0; i < numOfMessagesToRead; i++)
{
MSMQ.MSMQQueueInfo info = new MSMQ.MSMQQueueInfo();
info.FormatName = queueFormatName;
MSMQ.MSMQQueue mq = info.Open((int)(MSMQ.MQACCESS.MQ_ADMIN_ACCESS |
MSMQ.MQACCESS.MQ_PEEK_ACCESS), (int)MSMQ.MQSHARE.MQ_DENY_NONE);
object wantdest = false;
object tr = true;
object num = 0;
MSMQ.MSMQMessage msg = null;
if (i == 0)
msg = mq.PeekCurrent(ref wantdest, ref tr, ref num, ref wantdest);
else
msg = mq.PeekNext(ref wantdest, ref tr, ref num, ref wantdest);
if (msg == null)
continue;
XmlDocument doc = new XmlDocument();
doc.LoadXml(System.Text.ASCIIEncoding.ASCII.GetString((byte[])msg.Body));
XmlNode NODE = doc.SelectSingleNode("descendant::string");
messages.Add(NODE.InnerText);
}
}
catch (Exception ee)
{
MessageBox.Show(ee.ToString());
}
return messages;
}
History
- 11 Jan 2008 - Article published.
- 15 Jan 2008 - First update - the
PeekMessage()
method implementation changed, and article formatting changed.