I am trying to have a Windows service run all the time in the background of my computer with no-one knowing. My Windows service downloads the content of my email inbox and puts it in my database.
My Windows service just seams to stop - it enters a log every 60 seconds and then stops about 10 mins in?
I have posted my code below. Can any one see or tell me a reason why?
Any help would be much appreciated.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Timers;
namespace EmailWindowsService
{
public partial class MyEmailService : ServiceBase
{
private DateTime lastRun;
private bool flag = true;
private static System.Timers.Timer aTimer;
public MyEmailService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MySource")) // every thing the windows service does is logged in server explorer
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLogEmail.Source = "MySource";
eventLogEmail.Log = "MyNewLog";
// Timer Code
aTimer = new System.Timers.Timer(1 * 60 * 1000); // 60 seconds
aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
aTimer.Enabled = true;
// Timer Code
}
protected override void OnStart(string[] args)
{
flag = true;
lastRun = DateTime.Now;
eventLogEmail.WriteEntry("Started");
}
protected override void OnStop()
{
eventLogEmail.WriteEntry("Stopped");
}
protected override void OnPause()
{
eventLogEmail.WriteEntry("Paused");
}
protected override void OnContinue()
{
eventLogEmail.WriteEntry("Continuing");
}
protected override void OnShutdown()
{
eventLogEmail.WriteEntry("ShutDowned");
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
RetriveEmailClass Emails = new RetriveEmailClass();
if (flag == true)
{
eventLogEmail.WriteEntry("In getting Email Method");
Emails.ServiceEmailMethod();
lastRun = DateTime.Now;
flag = false;
}
else if (flag == false)
{
if (lastRun.Date < DateTime.Now.Date)
{
Emails.ServiceEmailMethod();
eventLogEmail.WriteEntry("In getting Email Method");
}
}
}
}
}
See that your class has no errors, an error there could throw you whole service out.
Also try putting your timer into a method and only call it, not have it in your service code.
A windows service should always be made as an empty shell that just call's methods.
Couple of reasons that your Windows services stops running.
1. Unhandled exception in your code. Looking from you code snippet, please add exception handling in the OnTimedEvent() method.
2. You service may crashed for some reason. In this case, you can go to event viewer to find out the reason for the failure.
Hope this helps.
You most likely have an unhandled exception. It's hidden since you use System.Timers.Timer. That timer eats all unhandled exceptions instead of letting them crash your app.
That means that your app might look like it's running OK while it's not. A try/catch in the timer callback will prove that.
I do recommend that you use System.Threading.Timer instead since it do not work in that way.
Your code is straightforward enough except the source for your Emails.ServiceEmailMethod method. Does the method generate any exceptions? If so, they have not been trapped in your timer method. Try:
try { Emails.ServiceEmailMethod(); }
catch (Exception ex) { eventLogEmail.WriteEntry(ex.Message); }
Related
i'm facing a strange problem with a Timer in a Windows service. is my first windows service, so for start to learn i decide to create a service that each 10 seconds write in a .txt file what time is it.
i add the timer but looks like the timer never start.
can you help me to understand where i'm wrong?
here my code:
namespace testtimer
{
public partial class TestTimer : ServiceBase
{
public TestTimer()
{
InitializeComponent();
timer.Interval = 10000;
timer.Enabled = true;
}
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
}
private void timer_Tick(object sender, EventArgs e)
{
string date = System.DateTime.Now.ToString();
StreamWriter wr = new StreamWriter(#"C:\Users\xxx\Desktop\Test\testtimer.txt", true);
wr.WriteLine("\n" + "The Time is:" + "\t" + date);
wr.Close();
}
}
}
where i'm wrong?
thanks a lot for your help :)
Am guessing you are using a Windows.Forms timer (the component one, that you drag onto your design surface)....this needs a "window" and "message loop" in order to be able to process/receive the actual timer tick event.
When you're an NT service....you don't have a window...you're just a bit of code that has entry points that get called by the SCM (Service Control Manager).
You need to use a different type of timer that uses a thread, and will call back a function.
Best Timer for using in a Windows service
EDIT: I shortened the code example
I am coding in C#, trying to set up a timer.
I have done it before but this time it is not working at all.
I have looked through it countless times and cannot find whats wrong!
Please help!
The timer should start in the RestoreMana() method but it doesn't seem to.
The timer should then run restoreTimer_Elapsed() every one second (1000 milliseconds).
This also doesn't seem to be the case.
This code is for a Terraria TShock Plugin and uses packages from it, but the timer is from System.Timers. So can anyone please help? :D
Thanks!
ALT Pastebin link: http://pastebin.com/WU7j3aqe
//'Import' necessary packages
using System;
using TShockAPI;
using Terraria;
using TerrariaApi.Server;
using System.Timers;
namespace Restore
{
//Variables
private Timer restoreTimer = new Timer(1000);
public override void Initialize()
{
//Calls CallRestore() when /restore is typed
Commands.ChatCommands.Add(new Command("fmg.restore", CallRestore, "restore"));
//Setup the Timer
restoreTimer.Elapsed += new ElapsedEventHandler(restoreTimer_Elapsed);
restoreTimer.Interval = 1000;
restoreTimer.AutoReset = true;
restoreTimer.Enabled = false;
}
//There would usually be more code here but I shortened it
private void CallRestore(CommandArgs args)
{
RestoreMana(args);
}
//This doesn't get run
private void restoreTimer_Elapsed(object sender, ElapsedEventArgs e)
{
player.SendMessage("Timer", Color.Aqua);
}
//Starts restoreTimer
private void RestoreMana(CommandArgs args)
{
restoreTimer.Start();
}
}
}
NB: I hope you figured the issue now as you asked this about 1 month ago.
Anyway, as stated in the comments, I would say your problem seems to lie on this line:
restoreTimer.Enabled = false;
should rather be:
restoreTimer.Enabled = true;
... unless you're setting this boolean elsewhere before your call to restoreTimer.Start();
i have an application (.Net Framework 2.0!) where you can enter operations which will be executed at a given time.
Now i want to create a process which runs in background and does nothing else then waiting till the given time is reached and call the operation to run. The application should run things like making backup of specific parts of the computer, start updates, run batches, ... The backgroundworker will run over several month doing nothing else.
Using the code below would work but it seems a bit ugly. Is there any better solution?
while(true && !applicationClosing)
{
List<ExecProcess> processList = LoadStoredProcesses();
List<ExecProcess> spawnedProcesses = new List<ExecProcess>();
DateTime actualTime = DateTime.Now();
foreach(ExecProcess ep in processList)
{
if(ep.ExecutionTime < actualTime)
{
ep.Execute();
spawnedProcesses.Add(ep);
}
}
RemoveSpawnedProcesses(spawnedProcesses);
Thread.Sleep(1000);
}
Thank you verry much.
I would suggest using a Windows service which implements a timer that fires an event every n seconds. You can pickup your tasks from wherever you want, and queue them internally in the service and fire at given times. Just check the timestamps within the _executeTimer_Elapsed method. This is only a small sample, but it should be enough to get you started.
public class MyService : ServiceBase
{
private Timer _executeTimer;
private bool _isRunning;
public MyService()
{
_executeTimer = new Timer();
_executeTimer.Interval = 1000 * 60; // 1 minute
_executeTimer.Elapsed += _executeTimer_Elapsed;
_executeTimer.Start();
}
private void _executeTimer_Elapsed(object sender, ElapsedEventArgs e)
{
if (!_isRunning) return; // logic already running, skip out.
try
{
_isRunning = true; // set timer event running.
// perform some logic.
}
catch (Exception ex)
{
// perform some error handling. You should be aware of which
// exceptions you can handle and which you can't handle.
// Blanket handling Exception is not recommended.
throw;
}
finally
{
_isRunning = false; // set timer event finished.
}
}
protected override void OnStart(string[] args)
{
// perform some startup initialization here.
_executeTimer.Start();
}
protected override void OnStop()
{
// perform shutdown logic here.
_executeTimer.Stop();
}
}
I have a C# program that is constantly checking for new additions to an online DB. I have this code to have it check every 10 seconds
static void Main(string[] args)
{
boolean run = true;
while (run)
{
DBConnect Db = new DBConnect();
// do amazing awesome mind blowing cool stuff
Db.closeConnection();
// wait for 10 seconds
int wait = 10 * 1000;
System.Threading.Thread.Sleep(wait);
}
}
i have error reporting that posts to the DB and if a major error occurs the program shuts down. Outside of the specific errors within my function, is this method secure and efficient?
You should rewrite your program as a windows service, that way you do not need to rely on a user to be logged for your program to run.
If you do go with the service route, I would swap out the infinite loop for a timer.
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
int wait = 10 * 1000;
timer = new Timer(wait);
timer.Elapsed += timer_Elapsed;
// We don't want the timer to start ticking again till we tell it to.
timer.AutoReset = false;
}
private System.Timers.Timer timer;
protected override void OnStart(string[] args)
{
timer.Start();
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
try
{
DBConnect Db = new DBConnect())
try
{
// do amazing awesome mind blowing cool stuff
}
finally
{
Db.closeConnection(); //We put this in a finally block so it will still happen, even if an exception is thrown.
}
timer.Start();
}
catch(SomeNonCriticalException ex)
{
MyExecptionLogger.Log(ex, Level.Waring); //Log the exception so you know what went wrong
timer.Start(); //Start the timer for the next loop
}
catch(Exception ex)
{
MyExecptionLogger.Log(ex, Level.Critical); //Log the exception so you know what went wrong
this.Stop(); //Stop the service
}
}
protected override void OnStop()
{
timer.Stop();
}
}
Write it as a console program without the wait and set up a scheduled task to run it periodically. You want to run it every 10 seconds? Every minute? Just change the scheduled task.
You can use the Task Scheduler GUI, or the schtasks command line tool.
See Programs are not cats.
I would setup a windows service and use SqlDependency http://msdn.microsoft.com/en-CA/library/a52dhwx7(v=vs.80).aspx. That way when a change (which you specify) occurs in the database, it will trigger the OnChange event which you specify to do whatever it is you need to do. See the link for implementation details.
I have a third party library containing a class which performs a function asynchronously. The class inherits from the Form. The function basically performs a calculation based on data stored in a database. Once it has finished, it calls a _Complete event in the calling form.
What I would like to do is call the function synchronously but from a non-windows form application. The problem is, no matter what I do, my application blocks and the _Complete event handler never fires. From a windows form I can simulate the function running synchronously by using a "complete" flag and a "while (!complete) application.doevents", but obviously application.doevents isnt available in a non-windows form application.
Is there something that would stop me using the class's method outside of a windows form application (due to it inheriting from 'Form') ?
Is there some way I can work around this ?
Thanks,
Mike
At a stab it might be worth trying something like the following which uses a WaitHandle to block the current thread rather than spinning and checking a flag.
using System;
using System.Threading;
class Program
{
AutoResetEvent _autoEvent;
static void Main()
{
Program p = new Program();
p.RunWidget();
}
public Program()
{
_autoEvent = new AutoResetEvent(false);
}
public void RunWidget()
{
ThirdParty widget = new ThirdParty();
widget.Completed += new EventHandler(this.Widget_Completed);
widget.DoWork();
// Waits for signal that work is done
_autoEvent.WaitOne();
}
// Assumes that some kind of args are passed by the event
public void Widget_Completed(object sender, EventArgs e)
{
_autoEvent.Set();
}
}
I've got some more information on this problem (I'm working in the same team as mikecamimo).
The problem also occurs in the Windows Forms application, when replicated correctly. In the original OP, the problem didn't occur in the windows form because there was no blocking. When blocking is introduced by using a ResetEvent, the same problem occurs.
This is because the event handler (Widget_Completed) is on the same thread as the method calling Widget.DoWork. The result that AutoResetEvent.WaitOne(); blocks forever because the event handler is never called to Set the event.
In a windows forms environment this can worked around by using Application.DoEvents to poll the message queue and allow the event the be handled. See below.
using System;
using System.Threading;
using System.Windows.Forms;
class Program
{
EventArgs data;
static void Main()
{
Program p = new Program();
p.RunWidget();
}
public Program()
{
_autoEvent = new AutoResetEvent(false);
}
public void RunWidget()
{
ThirdParty widget = new ThirdParty();
widget.Completed += new EventHandler(this.Widget_Completed);
data = null;
widget.DoWork();
while (data == null);
Application.DoEvents();
// do stuff with the results of DoWork that are contained in EventArgs.
}
// Assumes that some kind of args are passed by the event
public void Widget_Completed(object sender, EventArgs e)
{
data = e;
}
}
In a non windows forms application, such as a Windows Service, Application is not available so DoEvents cannot be called.
The problem is one of threading and that widget.DoWork's associated event handler somehow needs to be on another thread. This should prevent AutoResetEvent.WaitOne from blocking indefinitely. I think... :)
Any ideas on how to accomplish this would be fantastic.
AutoResetEvent _autoEvent = new AutoResetEvent(false);
public WebBrowser SyncronNavigation(string url)
{
WebBrowser wb = null;
wb = new WebBrowser();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
wb.ScriptErrorsSuppressed = true;
wb.Navigate(new Uri(url));
while (!_autoEvent.WaitOne(100))
Application.DoEvents();
return wb;
}
void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
//throw new NotImplementedException();
_autoEvent.Set();
}
Do you have the source for the component? It sounds like it's relying on the fact it will be called from a WinForms environment (must be a good reason why a library inherits from Form!), but it's hard to know for sure.