I have started building up the windows service in the c# language. And i want to implement the timer feature inside it. But for some reason, the DoIt timer event handler is not getting fired during the debugging and i am not getting any exception also. I am trying to debug the windows service using Debug->Start new instance.
The line TraceLog.WriteTrace("Router Service Started"); does get hit and executed.
public partial class EntryPoint : ServiceBase
{
private const int TIMER_INTERVAL = 10000;
private System.Timers.Timer mvTimer = new System.Timers.Timer();
[MTAThread()]
[System.Diagnostics.DebuggerNonUserCode()]
public static void Main()
{
#if DEBUG
EntryPoint service = new EntryPoint();
service.Start();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new EntryPoint()
};
ServiceBase.Run(ServicesToRun);
#endif
}
public EntryPoint()
{
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
InitializeComponent();
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
Exception ex = (Exception)e.ExceptionObject;
if (ex != null)
{
Console.WriteLine(ex);
}
}
public void Start()
{
OnStart(null);
}
protected override void OnStart(string[] args)
{
TraceLog.SetTrace(ConfigurationManager.AppSettings["RouterTraceLog"]);
TraceLog.WriteTrace("Router Service Started");
mvTimer = new Timer();
mvTimer.Elapsed += new ElapsedEventHandler(DoIt);
try
{
mvTimer.Interval = TIMER_INTERVAL;
mvTimer.Enabled = true;
}
catch (Exception ex)
{
mvTimer.Interval = TIMER_INTERVAL;
TraceLog.WriteTrace(ex.Message);
}
}
private void DoIt(object sender, ElapsedEventArgs e)
{
TraceLog.WriteTrace("Inside DoIt :: " + DateTime.UtcNow.ToString());
}
protected override void OnStop()
{
mvTimer.Enabled = false;
TraceLog.WriteTrace("Router Service stopping");
}
Please suggest. I am missing something very small and not able to nail it down.
In debug mode, the application exits after the function OnStart finishes. There's nothing to stop the application from quitting.
What you need is add a Console.ReadLine(); to prevent the application from exiting.
#if DEBUG
EntryPoint service = new EntryPoint();
service.Start();
Console.ReadLine();
#else
You can read more at MSDN on How to: Debug Windows Service Applications
Related
This question already has answers here:
Better way to constantly run function periodically in C#
(3 answers)
Closed 2 years ago.
Id like to build a windows Service in C#.
This service needs to be run periodically like every 10s.
Questions:
What is the difference between Timers.timer and Threading.timer?
How can I call CheckingThings with parameters?
If i run this code, it does invoke CheckingThings more than once every second like declared in here:
_timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);
Here is what i've got so far:
public partial class WindowsService1 : ServiceBase
{
// Logging
private static Serilog.Core.Logger _logEvent;
public WindowsService1()
{
InitializeComponent();
}
public void OnDebug() {
OnStart(null);
}
protected override void OnStart(string[] args)
{
//Logging
try {
_logEvent = new LoggerConfiguration()
.WriteTo.File(AppDomain.CurrentDomain.BaseDirectory + #"Logs\Logfile.txt", rollingInterval: RollingInterval.Month)
.CreateLogger();
}
catch (Exception e)
{
_logEvent.Error("The logging service is not working as expected: {errorMsg}", e);
}
try
{
// initializing some data here
var autoEvent = new AutoResetEvent(true);
while (true)
{
_timer = new Timer(new TimerCallback(CheckingThings), autoEvent, 5000, 1000);
}
}
catch (Exception e) {
_logEvent.Error("An error occured while initializing service: {0}", e);
}
}
private static void CheckingThings(object stateInfo)
AutoResetEvent autoEvent = (AutoResetEvent)stateInfo;
//These things needs to run periodically every 10s
}
protected override void OnStop()
{
_logEvent.Information("Stopping Service ...");
}
}
Here's a skeleton for a service class that does something every minute, using a System.Timers.Timer:
public partial class XService : ServiceBase
{
private Timer _minute = new Timer(60000);
public XService()
{
InitializeComponent();
_minute.Elapsed += Minute_Elapsed;
}
//this is async because my 'stuff' is async
private async void Minute_Elapsed(object sender, ElapsedEventArgs e)
{
_minute.Stop();
try
{
//stuff
}
catch (Exception ex)
{
//log ?
}
finally
{
_minute.Start();
}
}
protected override void OnStart(string[] args)
{
_minute.Start(); //this or..
Minute_Elapsed(null, null); //..this, if you want to do the things as soon as the service starts (otherwise the first tick will be a minute after start is called
}
...
I typically stop my timers while I do my thing - no point starting a job that takes 10 minutes and then another one a minute later, hence the stop/try/finally/start pattern
Edit:
Here's the tail part of the class and how it's started/launched both in debug (inside visual studio) and in release (as an installed windows service):
//just an adapter method so we can call OnStart like the service manager does, in a debugging context
public void PubOnStop()
{
OnStop();
}
}// end of XService class
static void Main(string[] args)
{
#if DEBUG
new XService().PubStart(args);
Thread.Sleep(Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new XService()
};
ServiceBase.Run(ServicesToRun);
#endif
}
I have created a windows service using .Net framework 4.7 with C# as the language. This service basically fetches computer hardware information (CPU usage) and writes it to a log file (using log4net). After compiling the service in release mode, when i installed it using installutil, the service is created and upon starting the service, a file with same name as 'exe' file with extension of 'sys' gets created frequently and deleted as well. Now when i stop the service, it is no longer created. I have created few windows services in the past using .Net but never encountered such behavior.
Program.cs
static void Main()
{
#if DEBUG
Service serv = new Service();
serv.StartIt();
Thread.Sleep(20000);
serv.StopIt();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service()
};
ServiceBase.Run(ServicesToRun);
#endif
}
Service.cs
Timer timer = null;
public Service()
{
InitializeComponent();
timer = new Timer(1000);
timer.Elapsed += Timer_Elapsed;
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
SystemInfo si = new SystemInfo();
si.GetSystemInfo();
}
#if DEBUG
public void StartIt()
{
timer.Start();
}
public void StopIt()
{
timer.Stop();
}
protected override void OnStart(string[] args)
{ }
protected override void OnStop() { }
#else
protected override void OnStart(string[] args)
{
timer.Start();
}
protected override void OnStop()
{
timer.Stop();
}
#endif
Note: I am using OpenHardwareMonitor library to collect hardware information.
Link to the problem description
The windows service i coded is not working:
Intended funcionality: The service is supposed to receive messages from Windows Message Queue (MSMQ) and write the messages on .txt files.
It works when I run it not-as-a-service (directly from visual studio)
When I installed it as a service i can start it, but it doesn't do anything, not creating/writing .txt files anywhere
(I know it isn't writing the files elsewhere because when I run the program from VS the messages are still in the queue, so they weren't taken out by the service)
The difference between running it as a service and running it from visual studio is the next:
namespace ComponentAtrapador
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
#if DEBUG
Service1 myService = new Service1();
myService.startMethod();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
#endif
}
}
}
(so if i run it as DEBUG it will run without me having to install it as a service)
Here's the service's code:
namespace ComponentAtrapador
{
public partial class Service1 : ServiceBase
{
private System.Timers.Timer _timer;
private System.ComponentModel.IContainer components1;
private System.Diagnostics.EventLog eventLog1;
public void startMethod()
{
OnStart(null);
}
public Service1()
{
InitializeComponent();
eventLog1 = new System.Diagnostics.EventLog();
if (!System.Diagnostics.EventLog.SourceExists("MySource"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart");
_timer = new System.Timers.Timer();
_timer.Interval = 5000; // 5 seconds
_timer.Elapsed += new System.Timers.ElapsedEventHandler(this.OnTimer);
_timer.Start();
}
protected override void OnStop()
{
_timer.Stop();
}
public void OnTimer(object sender, System.Timers.ElapsedEventArgs args)
{
string nombreArchivo = "archivoMensaje";
MessageQueue messageQueue = new MessageQueue(#".\Private$\SomeTestName");
System.Messaging.Message[] messages = messageQueue.GetAllMessages();
System.Messaging.Message m = new System.Messaging.Message();
foreach (System.Messaging.Message message in messages)
{
message.Formatter = new XmlMessageFormatter(new String[] { "System.String,mscorlib" });
string text = message.Body.ToString();
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + nombreArchivo + Properties.Settings.Default.SettingNumero + ".txt", text);
Properties.Settings.Default.SettingNumero++;
Properties.Settings.Default.Save();
//Do something with the message.
}
// after all processing, delete all the messages
messageQueue.Purge();
//}
}
}
}
That is where Logs are so helpful, put couple of eventLog1.WriteEntry() inside your OnTimer method and you will see where is it failing.
I would check
how many messages I am getting.
I will put one eventLog1.WriteEntry() inside loop to see what is happening with each message etc...
Turns out the service didn't have enough permissions, fixed it by setting the serviceProcessInstaller of the service on visual studio to User, so that when i installed it it'd ask for credentials. Just had to type "./[username]" when it asked for my username for it to work.
Another way of fixing it would be going into the task manager > services > right click service > properties > security. And change the permissions there.
I have a simple Windows Service application that can be run as a service or application started by user double-click. The problem is that I have no logs from OnStop event handler. There is no problem with OnStart handler. Why I cannot see any logs from OnStop?
public partial class TransmedicomCentralService : ServiceBase
{
TransmedicomCentralWorker serverThread;
public TransmedicomCentralService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
// konfiguracja loggera
GostcompUtils.Logger.Level = GostcompUtils.LoggerLevel.Trace;
GostcompUtils.Logger.FileName = "nowyPlikLogow.txt";
GostcompUtils.Logger.Targets = new List<GostcompUtils.LoggerTarget>() { GostcompUtils.LoggerTarget.File };
base.OnStart(args);
GostcompUtils.Logger.Log("Rozruch serwisu", GostcompUtils.LoggerLevel.Info);
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
serverThread = new TransmedicomCentralWorker();
GostcompUtils.Logger.Log("Serwis uruchomiono", GostcompUtils.LoggerLevel.Info);
}
protected override void OnStop()
{
base.OnStop();
GostcompUtils.Logger.Log("Zatrzymywanie serwisu", GostcompUtils.LoggerLevel.Info);
serverThread.Dispose();
GostcompUtils.Logger.Log("Serwis zatrzymano", GostcompUtils.LoggerLevel.Info);
}
public static void Main(string[] args)
{
TransmedicomCentralService service = new TransmedicomCentralService();
if (Environment.UserInteractive)
{
service.OnStart(args);
Console.WriteLine("Press any key to stop program");
Console.Read();
service.OnStop();
}
else
{
ServiceBase.Run(service);
}
}
}
I have a windows service that I made for MY server...
I need to check every minute if there is some new info in my SQL Database.
So I made a windows service that create a Timer with interval of 1 minute.
But The windows service set the timer and ending the run.
It's goes like this:
Starting Service
Setting Timer with interval
Finishing and exiting Service <-- I want to keep it alive
As you can see the Service exit and I want the Windows service to run every minute without stopping....
I can see in the Event Viewer that there are the "Service started successfully." And the "Service stopped successfully."
What should I do?
P.S : I thought Timer should work with out exit... or may I wrong?
CODE:
Windows service:
static void Main(string[] args)
{
try
{
Utils.SetConfigFile();
var ServiceToRun = new TaoTimer();
ServiceToRun.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
TaoTimer:
public partial class TaoTimer : ServiceBase
{
List<TimerModel> timerList;
public TaoTimer()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
EventLog.WriteEntry("Started");
}
public void SetTimer(TimerModel timerModel)
{
int minute = 1000 * 60;
try
{
AlertTimer at = new AlertTimer(timerModel, minute);
at.Start();
}
catch
{
}
}
protected override void OnStop()
{
EventLog.WriteEntry("Stopped");
}
protected override void OnPause()
{
EventLog.WriteEntry("Paused");
}
protected override void OnContinue()
{
EventLog.WriteEntry("Continuing");
}
protected override void OnShutdown()
{
EventLog.WriteEntry("ShutDowned");
}
public void Start()
{
SetTimerList();
}
protected void SetTimerList()//Read Config from xml and start the timer
{
XElement root = XElement.Load(#"C:\TaoTimer\Data.xml");
timerList = new List<TimerModel>(from d in root.Descendants("Timer")
select new TimerModel(
d.Element("Id").Value.ToString(),
d.Element("Name").Value.ToString(),
d.Element("InterVal").Value.ToString(),
d.Element("TimeFormat").Value.ToString(),
d.Element("Day").Value.ToString(),
d.Element("TimeStamp").Value.ToString()));
timerList.ForEach(i => SetTimer(i));
}
}
AlertTimer:
public class AlertTimer
{
static System.Timers.Timer aTimer = new System.Timers.Timer();
public AlertTimer(TimerModel timerModel, int milliseconds)
{
aTimer.Elapsed += new ElapsedEventHandler((sender, e) => OnTimedEvent(sender, e, timerModel));
aTimer.Interval = milliseconds;
}
public void Start()
{
aTimer.Enabled = true;
}
public static void OnTimedEvent(object source, ElapsedEventArgs e, TimerModel timerModel)
{
getAbsenceContacts.Start();<-- NEVER GETS HERE....
}
}
You're not actually starting your service. You're calling a method named Start, which is not part of the Windows Service class hierarchy it's just a method you've defined. Your method runs and finishes, so the service exits.
Try this:
static void Main(string[] args)
{
try
{
Utils.SetConfigFile();
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new TaoTimer()
};
ServiceBase.Run(ServicesToRun);
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
public partial class TaoTimer : ServiceBase
{
...
protected override void OnStart(string[] args)
{
SetTimerList();
EventLog.WriteEntry("Started");
}
....
}
and remove the Start method from TaoTimer entirely.
You need to store your AlertTimer instances in something that will last the lifetime of the service (e.g. in a List<AlertTimer> declared as a field inside TaoTimer.
It's only really alluded to in the documentation for Timer that timer's, in and of themselves, don't prevent themselves from being garbage collected. The example says:
// Normally, the timer is declared at the class level,
// so that it stays in scope as long as it is needed.
// If the timer is declared in a long-running method,
// KeepAlive must be used to prevent the JIT compiler
// from allowing aggressive garbage collection to occur
// before the method ends. You can experiment with this
// by commenting out the class-level declaration and
// uncommenting the declaration below; then uncomment
// the GC.KeepAlive(aTimer) at the end of the method.
//System.Timers.Timer aTimer;
Now, whilst your timer's are declared at the class level inside of your AlertTimer class, there's nothing to stop the AlertTimer instances, themselves, from being collected. And the GC only keeps things alive that are transitively reachable. Once the AlertTimer instances are collectible, so are your Timer objects.