Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Processing MSMQ Message in Windows Service

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);
        }
    }
}
like image 887
LCJ Avatar asked Mar 28 '12 16:03

LCJ


People also ask

Is MSMQ still supported?

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.


1 Answers

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; 
}
like image 50
Albin Sunnanbo Avatar answered Sep 30 '22 15:09

Albin Sunnanbo