I have several services that run correctly 99.9% of the time. However, they work with network and database and occasionally an error that I have not anticipated makes it into the code and causes the service to crash. In this instance, restarting the service usually fixes the problem.
My service creates a new thread where the main code is run. I have added error handling to the service class that catches and logs any unhandled exceptions from this thread. What I am wondering is if I can call OnStop and then OnStart from the service class to restart my service?
The code that I am using is in located in the same class as OnStart and OnStop. I have posted it below:
private void ExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
log.Append("Fatal Exception:\n" + args.ExceptionObject);
eventLog.WriteEntry(log.ToString());
log = new StringBuilder();
OnStop();
if (numberOfCrashes++ < 10)
{
Thread.Sleep(60000);
OnStart(null);
log.Append("The service has been restarted " + numberOfCrashes + " times.");
eventLog.WriteEntry(log.ToString());
log = new StringBuilder();
}
}
What I am wondering is if I can call OnStop and then OnStart from the
service class to restart my service?
This will depend on how you've implemented your OnStart and OnStop logic.
For example, if your OnStart is able to determine if the working thead is already started and, if so, it stops and starts it again, then yes, you may be able to simulate a service restart by directly calling these methods.
Thus, your actual code on OnStart and OnStop is the right answer to your question, and it's up to you to refactor it to cover your requirement of programatically-restarting your service without restarting the service at the operating system level.
Related
I made a Window service and let it work automatically and under localsystem account, when the service starts it fires this message for me and then stops
The [service name] service on local computer started and then stopped. Some Services stop automatically if they are not in use by another services or programs.
What's the problem and what's the solution?
Either you are not starting any threads on the OnStart method to do work, or there is an exception raised within your OnStart method.
If an exception is thrown, it will appear in the Windows Event log. The Windows Event log is a good place to start in any case.
Generally an OnStart method looks like this:
Thread _thread;
protected override void OnStart(string[] args)
{
// Comment in to debug
// Debugger.Break()
// Do initial setup and initialization
Setup();
// Kick off a thread to do work
_thread = new Thread(new MyClass().MyMethod)
_thread.Start();
// Exit this method to indicate the service has started
}
This particular error message means what it says - that your service has started but then quite soon it exited for some reason. The good news is that your service is actually doing something, so you have the executable configured and running as a service properly.
Once started, for some reason it is quitting. You need to find out why this is. Add some debugging to tell you its up and running and known exit cases. If that doesn't reveal the problem then add some debugging to let you know it's still running and work backwards from when that stops.
Are you tracing out any debug information? Most likely an exception is being thrown during your initialization. I would trace out all your exceptions and use Debugview to view them.
I had a similar problem that occurred because my Event Logs were full and the service was unable to write to them. As such, it was impossible to debug by looking for messages in the Event Viewer. I put a try/catch and dumped the exception out to a file. I had to change the settings on my logs to fill as needed instead of every 7 days and this allowed the services to start.
Of course, the root of the problem for me is that I have a nVidia driver issue that is flooding my event logs and now I'm probably beating on the disk, but that's another issue.
Maybe you need to run the service as Local System Account. See this post by Srinivas Ganaparthi.
I had the same issue starting JBoss, then I changed the JAVA_HOME variable, it worked for me. It was the JBoss version that doesn't support the 1.6, it supports 1.5.
I had similar problem and it turned out in my case that the program simply crashed in OnStart method. It tried to read some file that it couldn't find but I suppose that any other program crash would give the same result. In case of Windows forms application you would get some error message but here it was just "your service started and stopped"
If you ever need, like me to read some files from the directory where Windows Service .exe is located, check this topic:
Getting full path for Windows Service
In my case, a method in my service, was being called recursively (as no terminate condition being true) and after specific time my service was being stopped.
This is my first WCF Library and I created it within a Windows Service, which I can access just fine and process through it, but unlike a normal library, I can't seem to access any of it's method classes outside of the Web Interface. The WCF Library has some threading within it that stays up until it needs to shutdown and I need the ability to tell this library the service is shutting down and it needs to close out the threads within itself gracefully. I'm guess I'm missing something simple, but maybe I can capture the Close() being called from within the WCF Library?
ServiceHost oServiceHost = new ServiceHost(typeof(WCFListener.MyClass));
oServiceHost.Open();
//wait until shutdown is called.
while (!_shutDownEvent.WaitOne(Timeout.Infinite));
//HERE I NEED TO TELL THE LIBRARY TO STOP ANY THREADS OR
//WITHIN THE WCF CAPTURE CLOSE() WAS CALLED.
if (oServiceHost != null)
{
//close out the WCF Listener service.
oServiceHost.Close();
oServiceHost = null;
}
I know how to launch the WCF Library as it's working and processing, but there are threads that are created within the WCF Libray and stay OPEN in the WCF Library. I need the WCF Library to start closing threads property when Windows tells my Windows Service it needs to stop. serviceHost.Close() doesn't kill the threads that have been created nor do I want it to. This is causing the Windows service to freeze waiting for the threads to stop.. I'm trying to figure out how I can tell the WCF Library this as it doesn't have a interface like an object. I'm sure this is simple and I'm overthinking it.
It is a little hard to understand what your problem actually is, but generally, you would proceed as follows:
Update I have assumed hypothetical MyLibraryClass.Initialize() and MyLibraryClass.Shutdown() methods, that your library provides, below.
So, your library would provide something like this:
public static class MyLibraryClass
{
public static void Initialize(ServiceHost serviceHost)
{
serviceHost.Closed += (...) {
// Cleanup when host closes.
Shutdown();
}
}
public static void Shutdown()
{
// Cleanup. E.g. stop threads, etc.
}
}
If that is not correct, you need to provide more source/context in your question about what you can do or can't do. In general, it is always a good idea to not have explicit active components in a library (like threads, etc.); if required to do so, than you should provide an "initialize" and/or "shutdown" method for the users of your library.
public class MyService : ServiceBase
{
private ServiceHost serviceHost;
protected override void OnStart(string[] args)
{
serviceHost = /* new, etc. */
// Somehow pass the serviceHost reference to your library,
// then subscribe to `Closed`, e.g.
MyLibraryClass.Initialize(serviceHost);
serviceHost.Open();
}
protected override void OnShutdown()
{
serviceHost.Close();
// Do additional cleanup, e.g. stopping your "library threads"
// Alternative to the event-approach in "OnStart", simply call
MyLibraryClass.Shutdown();
}
}
That is, you would open your host when the service starts, and close it when the service ends. There should be no reason to do any extra "waiting", etc. on a service shutdown.
The Windows Service Control Manager will call (via P/Invoke, etc.) the OnStart and OnShutdown methods when it starts / stops the service.
The important thing is, that you do your actual work in a background thread, i.e. exit the OnStart and OnShutdown methods as quick as possible - that is a trait that you get for free with ServiceHost in this case.
I have created a windows service by using (Visual Studio 8) and installed it by using installutil.exe tool, however I am not getting proper result from it as I did the following code on service start method.
protected override void OnStart(string[] args)
{
FileStream fs = new FileStream(#"e:\mcWindowsService.txt",
FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("m ready buddy");
m_streamWriter.Flush();
m_streamWriter.Close();
}
Instead of creating file in E Drive it is showing Following Error when I am staring it !
The Test Service Installer service on Local Computer started and then stopped. Some services stop automatically if they are not in use by other services or program.
Put the above code in Try-Catch block, write it to event log for any exceptions and investigate it. Also would be good to put them in separate thread to avoid any block.
If you run the service from the a console, then make sure that your account has permissions on the E driver.
If you have installed your service, and realized that it threw the exception, then set the account type for the service installer like
var serviceInstaller = new ServiceProcessInstaller();
serviceInstaller.Account = ServiceAccount.LocalSystem;
I'm almost positive your code crashes. The try-catch suggestion above is the best so far so you can see what blows up.
Further:
Try to not execute stuff that takes a long time in the OnStart - only light initialization stuff. There's a timeout and if you go past that treshold Windows will complain that it cannot start it - it will remain in Starting state which is annoying.
In OnStart start just a timer and execute your heavy stuff in the handler of the expiration event of that timer's interval timer_Elapsed. Before you execute your stuff pause the timer and start it back after the operation ended.
I'm not using a Windows Form Timer--I'm using a System.Threading.Timer. No exceptions are raised when instantiating the timer, and to my understanding, System.Threading.Timer's do not need to be explicitly started.
I've tried using a System.Timers.Timer (See comments in code) and changing the signature of the callback with no luck. Inside the callback method, I stubbed in some EventLog writes, and not even the first writes to the event log. All I see in the Event Log is MyService.OnStart fired followed by MyService started (these are both from the OnStart event). Why aren't the timer callback events firing?
public partial class MyService : ServiceBase
{
private static System.Threading.Timer timer;
public MyService()
{
InitializeComponent();
if (!System.Diagnostics.EventLog.SourceExists("MyService"))
{
System.Diagnostics.EventLog.CreateEventSource(
"MyService", "MyServiceLog");
}
eventLog1.Source = "MyService";
eventLog1.Log = "MyServiceLog";
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("MyService.OnStart event fired");
// setup timer to poll and execute an event
//Timer timer = new Timer(new TimerCallback(CheckCalls), null, 0, 10000);
try
{
timer = new System.Threading.Timer(new System.Threading.TimerCallback(CheckCalls), null, 0, 10000);
}
catch (Exception ex)
{
eventLog1.WriteEntry(ex.Message + " Stacktrace: " + ex.StackTrace);
}
eventLog1.WriteEntry("MyServicestarted");
GC.KeepAlive(timer);
}
}
and the callback method, CheckCalls:
private static void CheckCalls(object objectState)
{
EventLog eventLog1 = new EventLog("MyServiceLog", "DAVIDWIN7", "MyService");
eventLog1.WriteEntry("MyService is polling");
}
Arg--For some reason when you Build->Clean Solution, then Build->Build Solution, Visual Studio does not rebuild your setup project. I believe my code above works fine, but I had tried many different fixes without explicitly right-clicking the setup project and selecting Build.
I thought Clean Solution would force all projects to be rebuilt on next build???
it's got to be an error with the timer thread writing to the event log.
I got it working on my computer but I replaced all the eventlog with Console.writeline because I didn't want to mess with my event log permissions.
Did you check if the account under which the service is running has access to the eventlog?
Please can you go and download this test application which mirrors exactly the scenario you are talking about:
https://docs.google.com/leaf?id=0Bw_NnV9fhgmgMThjNDgzOTgtODNiOC00NDE1LWEyMTYtNzVhOTMyNzlmZjZk&hl=en&authkey=CMuupNkC
I've just created this. It's a service that effectively uses the same code as you. The only difference is that I have used the toolbox to drag and drop an eventlog on to the service designer - setting the log to 'Application' and the source to 'Service1'.
Open a VS command prompt at the project folder, go to bin\debug and run installutil windowsservice1.exe - specifying some credentials (so you're installing the dev service directly from your bin output folder).
Start the service and monitor the application log - it will write every ten seconds as you expect to see from your code.
Assuming this works on your machine(tm) like it does on my machine(tm) then I would suggest that the problem is the event logging itself, or, horror of horrors - your service isn't running from your build output folder (most of the devs in my team insist on running their dev services from a different folder and then swear when they forget to actually update the binaries when they start debugging it!).
As I suggested in my comment, you really need to be able to attach the debugger to this and breakpoint the callback to verify that it's not getting fired. I never rely on the eventlog for diagnostics messages simply because the log might be full, or permissions might prevent you etc etc - it might be a windows platform component, but it's not as reliable as I would like.
The debugger, however, rarely lies (unless the deployed binaries are out of date ;) ). Compile a debug build of your project and make sure it's the one that is installed in the services list, start it up and then attach directly to the service exe (there's no point trying to attach to [service].vshost.exe - VS cannot auto-attach or host windows services as the only way they can run is via svchost.exe shelling them).
Hope this helps.
I have a standard windows server that inherits from the ServiceBase class.
On the OnStart method I want to check for certain conditions before I get to the main purpose of what my service does.
For example:
protected override void OnStart(string[] args)
{
if (condition == false)
{
EventLog.WriteEntry("Pre-condition not met, service was unable to start");
// TODO: Convert service state to "Stopped" because my precondition wasn't met
return;
}
InnitializeService();
}
Anybody have a good example for how a service can control its own state?
Throw an Exception. This will cause the services MMC to get an error - and the exception message and stack will automatically be logged to the event log. I use ApplicationException in this case.
In addition, the service will return to the "not running" state.
If you need to stop later on, you can call the Stop method on your ServiceBase.
The error shown the user in the "Computer Management" MMC app does not seem to get the exception text correctly in Vista. It shows the following:
The "your service name here" service
on Local Computer started and then
stopped. Some services stop
automatically if they are not in use
by other services or programs.
However it writes correctly to the Event Log just fine.
Very Cool. Thanks.