I have a windows service for processing the MSMQ messages. It relies on the following logic
· There is a timer in the windows service. Every ten minute it will execute the method named “ProcessMessages”.
· Inside this method, it first creates a list of existing messageIds by calling GetAllMessages method of the queue.
· For each messageId, it receives the message (using ReceiveById) and stores it into a file
Is there a better way to achieve the message processing?
Reference: http://www.switchonthecode.com/tutorials/creating-a-simple-windows-service-in-csharp
Note: The following code does not give the desired result when I made it as a service; however there is no error in event viewer (I am not doing any explicit logging). It was working fine when it was a simple console app. How to correct it? [Now it is working when I changed the accoun to "User" as shwon in the comments below]
My actaul requirement is to process all messages at fixed time slots – say at 10 AM and 11 AM only (on each day). What is the best approach to do this?
namespace ConsoleSwitchApp
{
class Program : ServiceBase
{
private static Timer scheduleTimer = null;
static MessageQueue helpRequestQueue = null;
static System.Messaging.XmlMessageFormatter stringFormatter = null;
static void Main(string[] args)
{
ServiceBase.Run(new Program());
}
public Program()
{
this.ServiceName = "LijosService6";
//Queue initialize
helpRequestQueue = new MessageQueue(@".\Private$\MyPrivateQueue", false);
stringFormatter = new System.Messaging.XmlMessageFormatter(new string[] { "System.String" });
//Set Message Filters
MessagePropertyFilter filter = new MessagePropertyFilter();
filter.ClearAll();
filter.Body = true;
filter.Label = true;
filter.Priority = true;
filter.Id = true;
helpRequestQueue.MessageReadPropertyFilter = filter;
//Start a timer
scheduleTimer = new Timer();
scheduleTimer.Enabled = true;
scheduleTimer.Interval = 120000;//2 mins
scheduleTimer.AutoReset = true;
scheduleTimer.Start();
scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed);
}
protected static void scheduleTimer_Elapsed(object sender, ElapsedEventArgs e)
{
ProcessMessages();
}
private static void ProcessMessages()
{
string messageString = "1";
//Message Processing
List<string> messageIdList = GetAllMessageId();
foreach (string messageId in messageIdList)
{
System.Messaging.Message messages = helpRequestQueue.ReceiveById(messageId);
//Store the message into database
messages.Formatter = stringFormatter;
string messageBody = System.Convert.ToString(messages.Body);
if (String.IsNullOrEmpty(messageString))
{
messageString = messageBody;
}
else
{
messageString = messageString + "___________" + messageBody;
}
}
//Write File
string lines = DateTime.Now.ToString();
lines = lines.Replace("/", "-");
lines = lines.Replace(":", "_");
System.IO.StreamWriter file = new System.IO.StreamWriter("c:\\test" + lines + ".txt");
file.WriteLine(messageString);
file.Close();
}
private static List<string> GetAllMessageId()
{
List<string> messageIdList = new List<string>();
DataTable messageTable = new DataTable();
messageTable.Columns.Add("Label");
messageTable.Columns.Add("Body");
//Get All Messages
System.Messaging.Message[] messages = helpRequestQueue.GetAllMessages();
for (int index = 0; index < messages.Length; index++)
{
string messageId = (System.Convert.ToString(messages[index].Id));
messageIdList.Add(messageId);
messages[index].Formatter = stringFormatter;
messageTable.Rows.Add(new string[] { messages[index].Label, messages[index].Body.ToString() });
}
return messageIdList;
}
protected override void OnStart(string[] args)
{
base.OnStart(args);
}
protected override void OnStop()
{
base.OnStop();
}
}
}
namespace ConsoleSwitchApp
{
[RunInstaller(true)]
public class MyWindowsServiceInstaller : Installer
{
public MyWindowsServiceInstaller()
{
var processInstaller = new ServiceProcessInstaller();
var serviceInstaller = new ServiceInstaller();
//set the privileges
processInstaller.Account = ServiceAccount.LocalSystem;
serviceInstaller.DisplayName = "LijosService6";
serviceInstaller.StartType = ServiceStartMode.Manual;
//must be the same as what was set in Program's constructor
serviceInstaller.ServiceName = "LijosService6";
this.Installers.Add(processInstaller);
this.Installers.Add(serviceInstaller);
}
}
}
As a Windows component, MSMQ is technically “supported” as long as it's carried by a supported version of Windows. Since it exists in Windows 10 and Windows Server 2019, MSMQ will continue to live on until at least 2029—and much longer assuming it isn't removed from future versions of Windows.
A nice alternative to using a timer is to use the MessageQueue.BeginReceive
method and do work in the ReceiveCompleted
event. This way your code will wait until there is a message in the queue and then immediately process the message, then check for the next message.
A short stub (a complete example in the linked MSDN article.)
private void Start()
{
MessageQueue myQueue = new MessageQueue(".\\myQueue");
myQueue.ReceiveCompleted +=
new ReceiveCompletedEventHandler(MyReceiveCompleted);
myQueue.BeginReceive();
}
private static void MyReceiveCompleted(Object source,
ReceiveCompletedEventArgs asyncResult)
{
try
{
MessageQueue mq = (MessageQueue)source;
Message m = mq.EndReceive(asyncResult.AsyncResult);
// TODO: Process the m message here
// Restart the asynchronous receive operation.
mq.BeginReceive();
}
catch(MessageQueueException)
{
// Handle sources of MessageQueueException.
}
return;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With