Windows service with timer

110,677

Solution 1

First approach with Windows Service is not easy..

A long time ago, I wrote a C# service.

This is the logic of the Service class (tested, works fine):

namespace MyServiceApp
{
    public class MyService : ServiceBase
    {
        private System.Timers.Timer timer;

        protected override void OnStart(string[] args)
        {
            this.timer = new System.Timers.Timer(30000D);  // 30000 milliseconds = 30 seconds
            this.timer.AutoReset = true;
            this.timer.Elapsed += new System.Timers.ElapsedEventHandler(this.timer_Elapsed);
            this.timer.Start();
        }

        protected override void OnStop()
        {
            this.timer.Stop();
            this.timer = null;
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            MyServiceApp.ServiceWork.Main(); // my separate static method for do work
        }

        public MyService()
        {
            this.ServiceName = "MyService";
        }

        // service entry point
        static void Main()
        {
            System.ServiceProcess.ServiceBase.Run(new MyService());
        }
    }
}

I recommend you write your real service work in a separate static method (why not, in a console application...just add reference to it), to simplify debugging and clean service code.

Make sure the interval is enough, and write in log ONLY in OnStart and OnStop overrides.

Hope this helps!

Solution 2

You need to put your main code on the OnStart method.

This other SO answer of mine might help.

You will need to put some code to enable debugging within visual-studio while maintaining your application valid as a windows-service. This other SO thread cover the issue of debugging a windows-service.

EDIT:

Please see also the documentation available here for the OnStart method at the MSDN where one can read this:

Do not use the constructor to perform processing that should be in OnStart. Use OnStart to handle all initialization of your service. The constructor is called when the application's executable runs, not when the service runs. The executable runs before OnStart. When you continue, for example, the constructor is not called again because the SCM already holds the object in memory. If OnStop releases resources allocated in the constructor rather than in OnStart, the needed resources would not be created again the second time the service is called.

Share:
110,677

Related videos on Youtube

Nitin Kabra
Author by

Nitin Kabra

I am a programming enthusiast with a knack for automating manual business processes using the latest technologies available in the market. I help customers find their way to result-oriented solutions for their business requirements. Working with various Large, Small-Scale, Public/Private Enterprises, I'm responsible for major SDLC Stages/Phases & Digital platform architecture; I've delivered several projects in Online Book Keeping, Inventory Management, e-Commerce, Telemedicine, e-Procurement (RFP, Reverse & Forward Auction), Permission/Schedule Management, Sales, and Marketing in my career. To the challenges of budget and incomplete requirements, I focus on the client, delivering considerable value in small packages and down-to-earth look for quick wins.

Updated on July 09, 2022

Comments

  • Nitin Kabra
    Nitin Kabra almost 2 years

    I have created a windows service with timer in c#.net. it works fine while i debug/build the project in visual studio but it does not perform its operation after installation.

    What might be the reason behind this ?

    code :

    public partial class Service1 : ServiceBase
    {
            FileStream fs;
            StreamWriter m_streamWriter;
            Timer tm = new Timer();
    
            public Service1()
            {
                InitializeComponent();
    
                this.ServiceName = "timerservice";
    
                tm.Interval = 2000;
                tm.Tick += new EventHandler(PerformOperations);
                tm.Start();
    
                fs = new FileStream(@"c:\mcWindowsService.txt", FileMode.OpenOrCreate, FileAccess.Write);
    
                m_streamWriter = new StreamWriter(fs);
                m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
            }
    
            private void PerformOperations(object sener, EventArgs e)
            {
                //StreamWriter swr = new StreamWriter("c:\\test_from_database.txt",true);
    
                try
                {
                    OdbcConnection con = new OdbcConnection("DSN=liquor_data");
    
                    OdbcDataAdapter adp = new OdbcDataAdapter("", con);
    
                    DataSet ds = new DataSet();
    
                    string sql = "select * from item_group";
                    adp.SelectCommand.CommandText = sql;
    
                    adp.Fill(ds, "item_group");
    
                    foreach (DataRow dr in ds.Tables["item_group"].Rows)
                    {
                        //      swr.Write(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
    
                        //Console.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                        m_streamWriter.WriteLine(dr["group_name"].ToString() + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n");
                    }
    
                    m_streamWriter.Flush();
                }
    
                catch (Exception ex)
                {
                    // swr.Write("Error :"+ ex.Message + "\t\t" + DateTime.Now.TimeOfDay.ToString() + "\n"); }
                }
            }
        }
    
    • urlreader
      urlreader over 11 years
      does the account have permission to run the windows service after installation?
    • MattW
      MattW over 11 years
      Try uncommenting the catch to see if some error is being throw. Also check out the windows event logs for any errors.
    • user1703401
      user1703401 over 11 years
      Hard to believe this works on your dev machine. The Timer class you are using requires a message loop. Use a System.Threading.Timer instead.
    • StingyJack
      StingyJack over 6 years
      If you want to make sure the event isnt getting bullied out of the way by non-background threads, or lost quietly (timers have historically had the problem of losing events in win svc forever), you cant use a Timer at all.
  • António Almeida
    António Almeida almost 11 years
    "and write in log ONLY in OnStart and OnStop overrides." Why? Can't you write to a text file at each timer elapsed event? I'm having that problem ... I have my own function which writes to text file (log), but it is not working (just works on start and stop), can you help me to understand what's the problem?
  • T-moty
    T-moty almost 11 years
    Yes, you can also write into the timer_tick method, but for me is unnecessary (the main work method must write its log). Can you show me more (exception, etc..) ?
  • sanrns
    sanrns over 3 years
    Absolutely works well. Keeps doing the work as per the timed interval. Thanks!