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);
}
}
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'm trying to make a service that should execute my codes every second after my codes execution ends. But when I start the service and debug it, timer ticks more than one, I mean, my codes executed twice before first execution ends.
here is my codes ;
Timer timer1 = new Timer(1000);
bool _service_working = false;
protected override void OnStart(string[] args)
{
timer1.Elapsed += new ElapsedEventHandler(runProcess);
timer1.Enabled = true;
timer1.Start();
_service_working = false;
}
protected override void OnStop()
{
timer1.Enabled = false;
}
private void runProcess(object sender, ElapsedEventArgs e)
{
try
{
if (_service_working == false)
{
timer1.Enabled=false;
_service_working = true;
}
#region myCodes
}
catch (Exception ex)
{
_logService.insert_log(1022, 2, ex.Message, "Path : runProcess");
}
finally
{
_service_working = false;
timer1.Enabled = true;
}
}
When I debug it, timer ticks again at runProcess if block...
Assuming you're using System.Timers.Timer then Timer events are raised in a background thread usually which means without any locking your timer event methods can overlap.
An easy solution is to set AutoReset to false and instead in your timer event restart it once complete, for example:
private bool terminating;
public Service()
{
terminating = false;
timer = new Timer(1000);
timer.Elapsed += new ElapsedEventHandler(runProcess);
timer.Enabled = true;
timer.AutoReset = false;
}
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
terminating = true;
timer1.Stop();
}
private void runProcess(object sender, ElapsedEventArgs e)
{
// Do stuff
if (!terminating)
timer.Start(); // Restart timer
}
i have timer in my windows service, but the windows service does not do what it should do..
I want ask you, if i have good code with timer?
Part of my code (updated):
protected override void OnStart(string[] args)
{
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(getFileList);
timer.Interval = 10000;
timer.Enabled = true;
timer.AutoReset = false;
}
private void getFileList(object sender, EventArgs e)
{
//Work with xml...
DeleteOldBackupFiles();
}
private void DeleteOldBackupFiles()
{
string[] Oldfiles = Directory.GetFiles(backup);
foreach (string Ofile in Oldfiles)
{
FileInfo fi = new FileInfo(Ofile);
if (fi.LastWriteTime < DateTime.Now.AddMonths(-2))
{
fi.Delete();
}
}
}
After your ideas i edit my code, but result is the same..
protected override void OnStart(string[] args)
{
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(getFileList);
timer.Interval = 10000;
timer.Enabled = true;
timer.AutoReset = true;
}
You have most likely an error somewhere in your timer making it throw an exception. You will not detect that since System.Timers.Timer silently ignores all unhandled exceptions.
You'll therefore have to wrap all code with a try/catch block:
private void getFileList(object sender, EventArgs e)
{
try
{
DeleteOldBackupFiles();
}
catch (Exception ex)
{
//log exception or just put a breakpoint here.
}
}
Hence your timer is working, but you are doing something wrong in it.
I would change it to this:
protected override void OnStart(string[] args)
{
timer = new System.Timers.Timer();
timer.Elapsed += new ElapsedEventHandler(getFileList);
timer.Interval = 10000;
timer.AutoReset = false;
timer.Enabled = true;
}
private void getFileList(object sender, EventArgs e)
{
List<string> files = new List<string>();
try
{
FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create(****);
Setting AutoReset to false causes the Timer to fire just once. In other words, it's like an automatic Stop after the first firing of the Timer. So doing that means you don't need to Stop() the Timer in your getFileList method. This is an important distinction when the Timer interval is small. If you set AutoReset to true and call Stop() at the top of your handler, there's a small chance that your method will get called more than once. Setting AutoReset to false is a more definitive way to get the behaviour you desire.
Calling Start() and setting Enabled to true are redundant, so I removed the Start().
Interval is milliseconds, so I changed that to 10000.
Maybe you are having an Exception thrown somewhere in getFileList, possibly because the service is running with a Current Directory of c:\windows\system32\.
Add a reference to System.Windows.Forms then add Environment.CurrentDirectory = System.Windows.Forms.Application.StartupPath; in your void Main(...) before your service is created.
as #jgauffin pointed out, you should wrap your getFileList body in a 'try catch' and log the error to some absolute path like c:\errors.txt. otherwise you are just guessing whats wrong.
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>
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");
}