Reputation: 41
I have created a windows service app which has OnStart
method. The method will read a path from the app.config file, create an object, then the service write the object's overridden ToString()
method to a file with a StreamWriter
.
This is working when I manually start this service with "net start". So the OnStart
method called, object created and written its ToString
method to a file.
I set it as an automatic running service, when the Windows starts up.
My problem is, that this OnStart
method is not called after the service is being started by Windows. So I think when the windows starts running the services at start up, it launches my service just don't calling the OnStart
method.
Does anybody have the same issue or somebody have a solution for it?
OnStart method:
protected override void OnStart(string[] args)
{
filePath = configReader.ReadConfig("FilePath");
DateEvent dateEvent = new DateEvent(DateTime.Now, TimeLoggerCore.Events.STARTUP.ToString());
writer.WriteToFile(dateEvent, filePath, true, false);
}
Constructor:
public TimeLoggerService()
{
InitializeComponent();
configReader = new AppConfigReader();
writer = new CSVWriter();
}
Program.cs:
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new TimeLoggerService()
};
ServiceBase.Run(ServicesToRun);
}
Upvotes: 1
Views: 8345
Reputation: 2641
If the event viewer shows that the service was started successfully, your OnStart has been called and has been returned from. How did you determine that is was not called? I guess by the fact that your file has not been written to. The problem is likely not that your OnStart is not called but that the WriteToFile failed and/or it was written to a different location (e.g. you use a relative path which is different or unavailable during startup). I suggest the following procedure to check this:
Experiment a bit with all setting to make sure they work as intended.
Finally, also note this remark in the OnStart documentation:
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.
Upvotes: 1
Reputation: 11
I had the same issue with my service, and after a lot of digging I found out that the reason why OnStop and OnStart were not called is because of the windows fast startup option. I put logging in all the functions of the ServiceBase that can be overriden and the one that was called when I shut down my laptop was OnPowerEvent, not OnStop.
Everything was working as expected when I was restarting windows instead of shutting them down.
Hope that this will help someone.
Upvotes: 1
Reputation: 6174
Since your service starts when you attempt to start it from a command-line using net.exe start [ServiceName]
but fails to start when windows is started, perhaps it is encountering an exception during startup.
One important thing to note when building and working with a custom Windows service is that the Windows Event Log can be very helpful in tracking down problems. When errors occur in a service, it's worthwhile to log that error in the event log.
Another helpful to debug your running service in Visual Studio is to start your service then attach the VS debugger to it.
To get some Windows event log logging into your service, I suggest modifying your service's code to log its startup. Note that what I've posted here is simplified for this forum - I typically put all logging code into a separate class. This way I can use it throughout the life of my service. One important note - be sure to set the ServiceName
property of your main service class with an appropriate name - this should be done in Visual Studio at design time in the Properties window of the service designer.
private EventLog _eventLog;
/*
* Use the EventId enumeration to store event IDs that will be written with events
* to the Windows event log.
*/
enum EventId
{
ServiceStarting = 10,
ServiceStartNormal = 100,
ServiceStartFailure = 999;
}
protected override void OnStart(string[] args)
{
try
{
// remember the event log
_eventLog = EventLog;
// log start
LogMessage(_eventLog, "Service starting", EventLogEntryType.Information, EventId.ServiceStarting);
filePath = configReader.ReadConfig("FilePath");
DateEvent dateEvent = new DateEvent(DateTime.Now, TimeLoggerCore.Events.STARTUP.ToString());
writer.WriteToFile(dateEvent, filePath, true, false);
LogMessage(_eventLog, "Service started", EventLogEntryType.Information, EventId.ServiceStartNormal);
}
catch(Exception e)
{
LogMessage(_eventLog, e.ToString(), EventLogEntryType.Error, EventId.ServiceStartFailure);
}
}
private static void LogMessage(EventLog eventLog, string message, EventLogEntryType entryType, EventId eventId)
{
/*
* If the event source we want to log doesn't exist, create it.
* Note that this take admin privs, and creating the log source should be
* done during service installation. This is here as a secondary means
* to create the log in the event that it doesn't already exist.
*/
if (!EventLog.SourceExists(eventLog.Source)
{
EventLog.CreateEventSource(eventLog.Source, eventLog.Log);
}
eventLog.WriteEntry(message, entryType, (int) eventId);
}
After adding this code to your service, re-deploy it, restart your system, and then check the event log. At a minimum you should see a message logged at service start.
Upvotes: 1
Reputation: 29
As you mentioned Windows start up, did you place your executable in the startup folder? If yes, that will not work that way. You need to install the service in the windows service manager. Microsoft Description for installing services
Upvotes: -2