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"); }
}
}
}
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!
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.
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>
Related
Hi I wrote a method in my program which call a Rest Api and get some information.
I want to call every minute. I fill OnStart and OnStop and all timer_Elapsed in which my method is there. I install my service and start it but It just run just for the first time and never repeat again would if anyone know the solution help me. In advanced I thanked you
On start :
protected override void OnStart(string[] args)
{
///just for log to show program is working
ayandehBLL.Save_Log("Service started...", nameof(OnStart));
if (timer == null)
{
timer = new Timer();
timer.AutoReset = true;
timer.Interval = 3000; //*
Convert.ToDouble(ConfigurationManager.AppSettings["IntervalMinutes"]);
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Start();
}
}
protected override void OnStop()
{
timer.Stop();
timer.Enabled = false;
ayandehBLL.Save_Log("Service stoped", nameof(OnStop));
//WriteErrorLog("Test window service Stoped");
}
-----------------------------
private void timer_Elapsed(object source, System.Timers.ElapsedEventArgs e)
{
var a = ayandehBLL.GetProductCode();
ayandehBLL.Save_Log($"Request national code is {a}", "test");
if (a != null)
{
Request_DOM request = new Request_DOM();
request.ProductCode= a;
try
{
var result = ayandehBLL.GetMyProductInfo(request);
if (result != null)
{
ayandehBLL.Save_Log(JsonConvert.SerializeObject(result), nameof(OnStart));
}
else
{
ayandehBLL.Save_Log("GetMyProductInfo() returned null", nameof(OnStart));
}
}
catch (Exception ex)
{
ayandehBLL.Save_Log(ex.Message.ToString(), "OnElapsedTime");
}
}
else
{
ayandehBLL.Save_Log("Request national code is null", "OnElapsedTime");
}
//WriteErrorLog("OnElapsedTime done");
}
The method triggered by a timer is being timed and run in a separate thread. If your main thread reaches the program end, the program will stop and the timer is discontinued. Therefore you have to capture the main thread before the end of the program in a loop where the program won't end until you want it to do so.
I've following code snippet for windows service and it is not hitting timer1_Elapsed which is the main function to execute my logic. I've gone through the code using debugging. I would like to seek suggestions from experts.
public partial class myService : ServiceBase
{
public myService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("myService Source"))
{
System.Diagnostics.EventLog.CreateEventSource(
"myService Source", "myService Log");
}
eventLog1.Source = "myService Source";
eventLog1.Log = "myService Log";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("myService service started on " + DateTime.Now.ToString());
System.Diagnostics.Debugger.Launch();
System.Diagnostics.Debugger.Launch();
string ProcessHour = ConfigurationManager.AppSettings["ProcessHour"];
int intProcessHour = Convert.ToInt32(ProcessHour);
DateTime dtNow = DateTime.Now;
if (dtNow.Hour < intProcessHour)
{
DateTime dtToday = DateTime.Today;
DateTime dtStartDateTime = dtToday.AddHours(Convert.ToDouble(ProcessHour));
System.TimeSpan diff = dtStartDateTime.Subtract(DateTime.Now);
timer1.Interval = diff.TotalMilliseconds;
timer1.Start();
}
else
{
DateTime dtToday = DateTime.Today;
DateTime dtStartDateTime = dtToday.AddDays(1).AddHours(Convert.ToDouble(ProcessHour));
System.TimeSpan diff = dtStartDateTime.Subtract(DateTime.Now);
timer1.Interval = diff.TotalMilliseconds;
timer1.Start();
}
}
protected override void OnStop()
{
eventLog1.WriteEntry("myService service stopped on " + DateTime.Now.ToString());
}
private void timer1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
try
{
timer1.Stop();
string StartTimer, EndTimer;
StartTimer = DateTime.Now.ToString();
eventLog1.WriteEntry("myService timer1_Elapsed begin on " + DateTime.Now.ToString());
/*Some Logic*/
}
catch (Exception ex)
{
}
}
}
Edit
InitializeComponent() does contain that function but still unable to make a hit.
private void InitializeComponent()
{
this.eventLog1 = new System.Diagnostics.EventLog();
this.timer1 = new System.Timers.Timer();
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.timer1)).BeginInit();
//
// timer1
//
this.timer1.Enabled = true;
this.timer1.Interval = 60000;
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(this.timer1_Elapsed);
//
// myService
//
this.ServiceName = "myService";
((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.timer1)).EndInit();
}
Unless you did it in the designer (so maybe it's into InitializeComponent()), you seem like you're missing to attach the event to timer1
timer1.Tick += timer1_Elapsed;
This should make the code work like you expect
If even this doesn't work, consider using the class System.Timers.Timer. Here's a reference that might help you understand the differences between Timer classes
https://web.archive.org/web/20150329101415/https://msdn.microsoft.com/en-us/magazine/cc164015.aspx
I'm writing Windows Service that calls for method after defined period of time (for now its 20 seconds). Everything was working fine until it didn't. Can't seem to find the cause of the problem.
Service seems to start and stop properly giving log entry, but it seems like it doesnt call for elapsed event.
public partial class UssPwdSyncService : ServiceBase
{
private Timer timer1 = null;
public UssPwdSyncService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
timer1 = new Timer();
this.timer1.Interval = 20000;
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_tick);
timer1.Enabled = true;
LogHandling.WriteErrorLogs("Service has started! LOg!");
}
catch (Exception ex)
{
LogHandling.WriteErrorLogs(ex);
}
}
private void timer1_tick(object sender, ElapsedEventArgs e)
{
ConfigurationManager.RefreshSection("connectionStrings");
foreach (ConnectionStringSettings cStr in ConfigurationManager.ConnectionStrings)
{
string name = cStr.Name;
string connString = cStr.ConnectionString;
string provider = cStr.ProviderName;
LogHandling.WriteErrorLogs(name + " " + connString + " " + provider);
}
LogHandling.WriteErrorLogs("This does something!");
}
protected override void OnStop()
{
timer1.Enabled = false;
LogHandling.WriteErrorLogs("Service has stoped!");
}
}
Could someone point out what am I missing?
I moved try catch to timer1_tick method.
This is the right place to exception check.
You can be throwing an exception o timer1_tick peace of code.
You have connectionStrings sections?
Note: i prefer to use Start and Stop methods instead of Enabled = true
and Enabled = false.
Two ways are right.
Try this:
public partial class UssPwdSyncService : ServiceBase
{
private Timer timer1 = null;
public UssPwdSyncService()
{
InitializeComponent();
this.timer1 = new Timer();
this.timer1.Interval = 20000;
this.timer1.Elapsed += new System.Timers.ElapsedEventHandler(timer1_tick);
}
protected override void OnStart(string[] args)
{
this.timer1.Start();
LogHandling.WriteErrorLogs("Service has started! LOg!");
}
private void timer1_tick(object sender, ElapsedEventArgs e)
{
try
{
ConfigurationManager.RefreshSection("connectionStrings");
foreach (ConnectionStringSettings cStr in ConfigurationManager.ConnectionStrings)
{
string name = cStr.Name;
string connString = cStr.ConnectionString;
string provider = cStr.ProviderName;
LogHandling.WriteErrorLogs(name + " " + connString + " " + provider);
}
LogHandling.WriteErrorLogs("This does something!");
}
catch (Exception ex)
{
LogHandling.WriteErrorLogs(ex);
}
}
protected override void OnStop()
{
this.timer1.Stop();
LogHandling.WriteErrorLogs("Service has stoped!");
}
}
I assume you're using the Timer in System.Timers. You need to call the timer's Start() method.
My code is:
public partial class MainService : ServiceBase
{
public MainService()
{
InitializeComponent();
}
private void timer1_Tick(object sender, System.EventArgs e)
{
TextWriter file = new StreamWriter("C:\\logfile.txt", true);
file.WriteLine("CPU Usage : " + System.DateTime.Now);
file.Close();
}
protected override void OnStart(string[] args)
{
timer1.Enabled = false;
TextWriter file = new StreamWriter("C:\\logfile.txt", true);
file.WriteLine("Service Started");
file.Close();
timer1.Interval = 1000;
timer1.Tick+=new EventHandler(timer1_Tick);
timer1.Enabled = true;
timer1.Start();
}
protected override void OnStop()
{
TextWriter file = new StreamWriter("C:\\logfile.txt", true);
file.WriteLine("Service Restarted");
file.Close();
}
protected override void OnContinue()
{
TextWriter file = new StreamWriter("C:\\logfile.txt", true);
file.WriteLine("Service stopped");
file.Close();
}
}
The code write the time of system each one second. But it run only two times(on OnStart and OnStop). How to keep it live? who explain to me the lifecircle of window service
The problem is that you are using System.Windows.Forms.Timer. This particular component is intended for UI threads that need to do some processing. Windows services do not have UI threads, so this is the wrong choice of timer. More specifically, the problem is that Windows services do not have a UI message pump, so the Tick event is never processed. Replacing System.Windows.Forms.Timer with System.Timers.Timer will give you the expected results (see below).
A few suggestions for you.
Unless you have a pressing need to open and close the file each time you wish to write to it, I would suggest making your System.IO.TextWriter a class variable, open the file in OnStart(), and close it in OnStop().
If you'll put a call to System.Diagnostics.Debugger.Launch() in your OnStart() for example, you'll be prompted to jump into a debug session when you start your service. This will allow you to debug things as you move along.
The OnContinue() callback does not occur when the service is stopped. It occurs when the service is resumed after having been paused. Thus your messages are out of place. The "Service stopped" message should be logged in the OnStop() method. In practice, I haven't seen a need for implementing the pause/resume functionality, so you might consider whether you truly need it in your service.
On with the code...
public partial class Service1 : ServiceBase
{
System.Timers.Timer timer = new System.Timers.Timer();
System.IO.TextWriter file;
public Service1()
{
// Uncomment this line to launch the debugger when starting the service.
//System.Diagnostics.Debugger.Launch();
InitializeComponent();
}
protected override void OnStart(string[] args)
{
file = new StreamWriter("C:\\logfile.txt", true);
file.WriteLine("Service Started");
timer.AutoReset = true;
timer.Interval = 1000;
timer.Elapsed += OnTimerElapsed;
timer.Start();
}
protected override void OnStop()
{
timer.Stop();
timer.Dispose();
file.WriteLine("Service Stopped");
file.Close();
}
private void OnTimerElapsed(object sender, System.Timers.ElapsedEventArgs e)
{
file.WriteLine("CPU Usage : " + System.DateTime.Now);
}
}
I wrote a windows service ,that will my class library every 15 mins interval to execute the class.
It works fine when i deployed the windows service in my machine,the timer works well and every 15 mins it calls my class library but when i deployed in my server,it works fine only on onstart after that its not raise the timer or every 15 mins suppose to call my class lib are not happening,some one please guide me what suppose to look here to identify the problem
here is my code
public partial class Service1 : ServiceBase
{
private Timer _timer;
private DateTime _lastRun = DateTime.Now;
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
Shell Distribute= new Shell();
Distribute.Distribute();
_timer.start();//this line was missed in my original code
}
protected override void OnStop()
{
this.ExitCode = 0;
base.OnStop();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//if (_lastRun.Date < DateTime.Now.Date)
//{
try
{
_timer.Stop();
Shell Distribute= new Shell();
Distribute.Distribute();
}
catch(exception ex)
{}
finally
{
_timer.Start();
}
//}
}
}
}
I strongly believe log on issues but am not sure for two reasons,if i start or restart this service in my test server using the same account works well but only timer is not working.
The code is exactly same so i don't worry much about my code bcoz it work timer based in my local machine using the same account.
Thanks in Advance.
Am not sure why my service working now based on timer,all i did is add the log in the code like below to find out what's going on but fortunately it works like a charm.
protected override void OnStart(string[] args)
{
log4net.Config.XmlConfigurator.Configure();
log.Debug("Service Called when Onstart");
_timer = new Timer(10 * 60 * 1000); // every 10 minutes
log.Debug("calling Distributor Method");
Shell Distributor = new Shell();
Distributor.Distribute();
log.Debug("calling timer Elapsed");
_timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
log.Debug("start the timer");
_timer.Start();
}
protected override void OnStop()
{
log.Debug("stop the timer in OnStop method");
this.ExitCode = 0;
base.OnStop();
}
private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
log.Debug("IN Timer Elapsed method");
try
{
log.Debug("IN try block and calling timer stop function");
_timer.Stop();
log.Debug("Distributor Method Called from try block");
Shell Distributor = new Shell();
Distributor.Distribute();
}
catch (Exception ex)
{
log.Debug("IN Catch Block");
log.Debug(ex.Message);
}
finally
{
_lastRun = DateTime.Now;
log.Debug("IN Final Block");
log.Debug("start the timer");
_timer.Start();
log.Debug("Exit the Timer Elapsed Method");
}