31

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"); }
            }
        }
    }
abatishchev
  • 92,232
  • 78
  • 284
  • 421
Nitin Kabra
  • 2,817
  • 9
  • 37
  • 59
  • does the account have permission to run the windows service after installation? – urlreader Oct 14 '12 at 18:27
  • Try uncommenting the catch to see if some error is being throw. Also check out the windows event logs for any errors. – MattW Oct 14 '12 at 19:01
  • 2
    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. – Hans Passant Oct 14 '12 at 20:29
  • 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. – StingyJack Oct 28 '17 at 20:14

3 Answers3

61

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!

SetFreeByTruth
  • 793
  • 7
  • 23
T-moty
  • 2,411
  • 21
  • 30
  • "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? – António Almeida May 26 '13 at 01:18
  • 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..) ? – T-moty May 26 '13 at 16:54
  • Absolutely works well. Keeps doing the work as per the timed interval. Thanks! – sanrns Jan 11 '21 at 06:34
7

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.

Community
  • 1
  • 1
Luis Quijada
  • 2,255
  • 1
  • 23
  • 31
0

Here's a working example in which the execution of the service is started in the OnTimedEvent of the Timer which is implemented as delegate in the ServiceBase class and the Timer logic is encapsulated in a method called SetupProcessingTimer():

public partial class MyServiceProject: ServiceBase
{

private Timer _timer;

public MyServiceProject()
{
    InitializeComponent();
}

private void SetupProcessingTimer()
{
    _timer = new Timer();
    _timer.AutoReset = true;
    double interval = Settings.Default.Interval;
    _timer.Interval = interval * 60000;
    _timer.Enabled = true;
    _timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // begin your service work
    MakeSomething();
}

protected override void OnStart(string[] args)
{
    SetupProcessingTimer();
}

...
}

The Interval is defined in app.config in minutes:

<userSettings>
    <MyProject.Properties.Settings>
        <setting name="Interval" serializeAs="String">
            <value>1</value>
        </setting>
    </MyProject.Properties.Settings>
</userSettings>
Uwe Köhler
  • 93
  • 1
  • 7