Windows Service Never Restarted from C# Code - c#

I have written a code to restart my windows service but it never works properly. Service is able to stop but never start again. My Project is self hosted WCF service inside a Windows Service. below is the code.
Restart Method
public static void RestartService(string serviceName)
{
try
{
ServiceController svc = new ServiceController(serviceName);
if (svc.Status == ServiceControllerStatus.Running) svc.Stop();
svc.WaitForStatus(ServiceControllerStatus.Stopped, new System.TimeSpan(0, 0, 20));
svc.Start();
svc.WaitForStatus(ServiceControllerStatus.Running, new System.TimeSpan(0, 0, 20));
svc.Dispose();
}
catch (Exception ex)
{
Logging.WriteException(ex);
}
}
Main Program
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
try
{
ServiceBase[] ServicesToRun =
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
catch (Exception)
{
}
}

The correct way to manage restart of services is by using Windows Service Recovery Actions, described here.
They allow you to tell the Service Control Manager what to do in the event of a failure, including any restart actions, how many times to attempt a restart, and how long to wait between attempts.
This is way more robust than anything you could write in the service code itself.

Related

How to re-start a console application if it crashes?

I have created a console application in C#. How can I program this application so that it will re-start itself after a crash?
If I understand your question correctly, you want to attempt to re-start a console app in the event of a crash. In C# console-apps the method defined as the entry point (usually static void main) is the root of the call stacks in the app. You essentially would need to call that method recursively. You will want to make sure that the app eventually fails if it is in some unintended or unrecoverable state.
For example in the main class:
static int retryCount;
const int numberOfRetries = 3;
static void Main(string[] args)
{
try
{
var theApp = new MyApplicationType(args);
theApp.StartMyAppLogic();
}
catch (ExpectedExceptionType expectThisTypeOfException)
{
thisMethodHandlesExceptions(expectThisTypeOfException);
}
catch (AnotherExpectedExceptionType alsoExpectThisTypeOfException)
{
thisMethodHandlesExceptions(alsoExpectThisTypeOfException);
}
catch (Exception unexpectedException)
{
if(retryCount < numberOfRetries)
{
retryCount++;
Main(args);
}
else
{
throw;
}
}
}
You can use a watchdog to process your monitor and restart it if crashed:
see: What's the best way to watchdog a desktop application?
You can use a windows service instead and set it's recovery options as indicated here: https://serverfault.com/questions/48600/how-can-i-automatically-restart-a-windows-service-if-it-crashes
You can use a scheduled task in task manager to start your application periodically , and set it to only start if previous run has ended:
https://support.microsoft.com/en-us/kb/323527
You could try something like this:
static void Main(string[] args)
{
try
{
// Application code goes here
}
catch (Exception)
{
var applicationPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
Process.Start(applicationPath);
Environment.Exit(Environment.ExitCode);
}
}
Basically, wrap all the code in a try/catch, and if any exceptions occur, the program will retrieve the .exe location with System.Reflection.Assembly.GetExecutingAssembly().Location; and then call Process.Start to run the application again.
You should control your console app from another application (watchdog, sheduler, procmon, servman, ...).
E.g. you can create your console app as a service and control it from service manager.

windows service will not stop when I select stop from the services windows C#

I have written a windows service but when I try to stop the service it says that the service cannot be stopped at this time. Here's my whole class:
public partial class RenewalsService : ServiceBase
{
private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
public RenewalsService()
{
InitializeComponent();
this.CanStop = true;
}
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThread)
{
Name = "Renewals Service Thread",
IsBackground = true
};
_thread.Start();
}
protected override void OnStop()
{
try
{
if (!_shutdownEvent.SafeWaitHandle.IsClosed)
{
_shutdownEvent.Set();
}
if (_thread.IsAlive)
{
if (!_thread.Join(3000))
{
// give the thread 3 seconds to stop
_thread.Abort();
}
}
}
catch (Exception ex)
{
// _thread.Join may raise an error at this point. If it does we dont care. We dont care about any other exceptions
// since we are already in the process of closing the service.
}
finally
{
IError logger = new Logger();
Exception ex = new Exception("The Renewals service has been stopped.");
logger.Log(this, SeverityEnum.Warning, ex);
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
}
}
private void WorkerThread()
{
try
{
while (!_shutdownEvent.WaitOne(1))
{
string timeToRun = ConfigurationManager.AppSettings["RunTime"];
string[] timeStrings = timeToRun.Split(':');
TimeSpan runtime = new TimeSpan(0, Int32.Parse(timeStrings[0]), Int32.Parse(timeStrings[1]), Int32.Parse(timeStrings[2]));
if (DateTime.Today.TimeOfDay.Hours == runtime.Hours &&
DateTime.Today.TimeOfDay.Minutes == runtime.Minutes)
{
Renewals renewals = new Renewals();
renewals.GenerateRenewal();
}
}
}
catch (Exception ex)
{
IError logger = new Logger();
logger.Log(this, SeverityEnum.Warning, ex);
this.OnStop();
}
}
}
What's missing to ensure the user can stop the service.
Your code looks ok to me, so here's a couple of things to check.
First, does the GenerateRenewal() method take a long time to complete? If so, you might need to periodically check _shutdownEvent inside that method for a timely shutdown. Of course, you've marked the thread as a background thread so it should shut down when you tell the service to stop anyway. I haven't seen background threads hold up process termination, but I guess there's always that chance.
Second, the more likely culprit to me is that the service has already shut down due to an exception. The Services console doesn't automatically refresh when a service shuts down, so it's possible you see the Stop link available to you when it shouldn't be. If you hit F5, the console will refresh, and if your service has stopped, the Start link should be the only one available. Check your log files to see if your exception handlers have been triggered.
UPDATE
So it looks like your WorkerThread() method is throwing an exception, which causes the service to stop. This explains why the Stop link is giving you the error message when you click it.
Providing you have sufficient permissions on your box, use this link to debug your service to find out why the exception is occurring.
HTH
The base ServiceBase class calls your overridden virtual method OnStop() when the Windows Service Control Manager ("the SCM") has sent the service a "Stop" command. In the method's implementation you are supposed to do whatever is necessary to get your service to a stopped state, then return from the method back to the ServiceBase class, which handles the interaction with the SCM, in this case to tell the SCM that your service is now stopped. The SCM will decide when your service process should be terminated, and the ServiceBase class handles that without you needing to do anything explicit.
For a well-behaved service, you should either just return at the end of your OnStop method, or throw an exception. The ServiceBase class will handle things appropriately, including logging your exception, if you have thrown one, as an error in the Windows Event Log. If your method may take a while to get your service stopped, you should call base.RequestAdditionalTime() at the appropriate points, so the base class can tell the SCM that you haven't just hung, your service is in the process of stopping.
I think your main problem lies in these lines:
Environment.ExitCode = 0;
Environment.Exit(Environment.ExitCode);
You never return to the base class at all... so the ServiceBase class never has a chance to respond gracefully to the SCM... you are just unilaterally terminating the process hosting your service. This is not what a well-behaved Windows service does.
The ServiceBase class is designed to be able to support multiple services hosted in a single service process. Individual services should not concern themselves with the lifetime of the host service process, only with the logical state of their own service.

Start Windows Service in C#

I want to start a windows service that was just installed.
ServiceBase[] ServicesToRun;
if (bool.Parse(System.Configuration.ConfigurationManager.AppSettings["RunService"]))
{
ServicesToRun = new ServiceBase[] { new IvrService() };
ServiceBase.Run(ServicesToRun);
}
The IvrService code is:
partial class IvrService : ServiceBase
{
public IvrService()
{
InitializeComponent();
Process myProcess;
myProcess = System.Diagnostics.Process.GetCurrentProcess();
string pathname = Path.GetDirectoryName(myProcess.MainModule.FileName);
//eventLog1.WriteEntry(pathname);
Directory.SetCurrentDirectory(pathname);
}
protected override void OnStart(string[] args)
{
string sProcessName = Process.GetCurrentProcess().ProcessName;
if (Environment.UserInteractive)
{
if (sProcessName.ToLower() != "services.exe")
{
// In an interactive session.
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new IvrInteractive());
IvrApplication.Start(); // the key function of the service, start it here
return;
}
}
}
I am not sure how to start the service. Using ServiceController.Start()? But I already have ServiceBase.Run(ServicesToRun); Is it for starting a service?
Code hint is definitely appreciated.
To answer the question about starting a service from code, you would want something like this (which would be equivalent to running net start myservice from the command line):
ServiceController sc = new ServiceController();
sc.ServiceName = "myservice";
if (sc.Status == ServiceControllerStatus.Running ||
sc.Status == ServiceControllerStatus.StartPending)
{
Console.WriteLine("Service is already running");
}
else
{
try
{
Console.Write("Start pending... ");
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, new TimeSpan(0, 0, 10));
if (sc.Status == ServiceControllerStatus.Running)
{
Console.WriteLine("Service started successfully.");
}
else
{
Console.WriteLine("Service not started.");
Console.WriteLine(" Current State: {0}", sc.Status.ToString("f"));
}
}
catch (InvalidOperationException)
{
Console.WriteLine("Could not start the service.");
}
}
This will start the service, but keep in mind that it will be a different process than the one that is executing the above code.
Now to answer the question about debugging a service.
One option is to attach after the service has been started.
The other is to make your service executable be able to run the main code, not as a service but as a normal executable (typically setup via a command line parameter). Then you can F5 into it from your IDE.
EDIT: Adding sample flow of events (based on questions from some of the comments)
OS is asked to start a service. This can be done from the control panel, the command line, APIs (such as the code above), or automatically by the OS (depending on the service's startup settings).
The operating system then creates a new process.
The process then registers the service callbacks (for example ServiceBase.Run in C# or StartServiceCtrlDispatcher in native code). And then starts running its code (which will call your ServiceBase.OnStart() method).
The OS can then request that a service be paused, stopped, etc. At which point it will send a control event to the already running process (from step 2). Which will result in a call to your ServiceBase.OnStop() method.
EDIT: Allowing a service to run as a normal executable or as a command line app: One approach is to configure your app as a console application, then run different code based on a command line switch:
static void Main(string[] args)
{
if (args.Length == 0)
{
// we are running as a service
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run(ServicesToRun);
}
else if (args[0].Equals("/debug", StringComparison.OrdinalIgnoreCase))
{
// run the code inline without it being a service
MyService debug = new MyService();
// use the debug object here
}
First you need to install the service using InstallUtil, e.g.
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe C:\MyService.exe
You need to start the service from the command line, e.g.
net start ServiceName // whatever the service is called
Then you need to attach to the process with Visual Studio, via Tools > Attach To Process.
Stick the breakpoints in the solution wherever you want it to break and the dev environment should take over.
To start it from the dev environment, put the net start ServiceName command into a batch file, and then in the Project Properties > Build Events "Post Build Event Command Line" you can add the path to the batch file.
*note that looking now, I'm not sure if you need to even use a batch file, you might be able to put the command directly in there. Try and edit this answer with whatever works.

Zero application endpoint error when I try to start a service

I think I've literally checked for all possibilities but I still keep getting this error (written in eventvwr) when I attempt to start my service:
Service cannot be started. System.InvalidOperationException: Service
'NexolNotifierWinService.NexolNotifier' has zero application
(non-infrastructure) endpoints. This might be because no configuration
file was found for your application, or because no service element
matching the service name could be found in the configuration file, or
because no endpoints were defined in the service element.
Service installation goes smoothly using installutil.
I'm genuinely not sure why I'm having this error. It's just a simple Windows Service project, so there's no app.config to mess around with either.
Here's my code:
Program.cs
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new NexolNotifierService()
};
ServiceBase.Run(ServicesToRun);
}
}
NexolNotifierService.cs
public partial class NexolNotifierService : ServiceBase
{
private ServiceHost host;
public NexolNotifierService()
{
InitializeComponent();
this.ServiceName = "NexolNotifierService";
}
protected override void OnStart(string[] args)
{
Type serviceType = typeof(NexolNotifier);
host = new ServiceHost(serviceType);
host.Open();
}
protected override void OnStop()
{
if (host != null)
host.Close();
}
}
ProjectInstaller.Designer.cs (For installing service)
private void InitializeComponent()
{
this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// serviceInstaller1
//
this.serviceInstaller1.ServiceName = "NexolNotifierService";
this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
//
// ProjectInstaller
//
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.serviceInstaller1});
}
and my actual service:
NexolNotifier.cs
public class NexolNotifier
{
public NexolNotifier()
{
....
}
Service was added from add new project->Windows Service in Visual Studio 2008.
I'm just trying to get a very simple windows service working. From what I can see, there is zero reason why this shouldn't work.
What do you want to do?
If you want just a plain Windows Service - no communication, nothing - then you don't need ServiceHost! You just need to derive from the ServiceBase class in the .NET framework and implement/override some of the methods - that's all. Read values from a database, do something with them, send e-mails - whatever - you will never need a ServiceHost for this!
If you use ServiceHost then you're using the WCF infrastructure, which means, you're writing a self-hosted web service.
So what do you want to do, really??
What's the task/job that your Windows Service is supposed to do?? ServiceHost has nothing to do with a plain Windows Service! ServiceHost == WCF - always. You don't need a ServiceHost for just a plain Windows service
For just plain Windows service (no WCF), see e.g.
Creating a Basic Windows Service
Simple Windows Service Sample
and many, many more samples. Both samples show just a plain Windows service, no WCF, no ServiceHost anywhere in sight.
Add service endpoint from code like this
Uri baseAddress = new Uri("http://localhost:8095/Service");
serviceHost = new ServiceHost( typeof(YourService), baseAddress );
serviceHost.AddServiceEndpoint( typeof(IYourService), new BasicHttpBinding(), baseAddress );
serviceHost.Open();

Silently update a Windows service

I have built a Windows service, now I want it to auto-update. I have read about a creating a second service to do that or different program , cant use click one, what about myBuild? Does anyone know it? What is the best way? Can I just change assemblies?
If you want your service to run while you are performing an update, here is what I had done before to achieve this:
Put your updateble logic into a separate DLL.
Create an AppDomain within your service.
Create file monitor that fires an event whenever you copy that file (you can use MSFT Ent Lib Updates)
Unload the old dll while blocking (queue) the threads that execute stuff from that dll
Load in the new dll file into the app domain.
Let your threads know to continue processing.
Download the new exe and any additional assembly's.
Rename your existing assembly's.
Copy in your new assembly's.
Restart Service. You can build the service restart function into your main service exe.
When service starts check for renamed files from step 2 and delete them to clean up.
To restart your service do
System.Diagnostics.Process.Start
(System.Reflection.Assembly.GetEntryAssembly().Location)
Then in your service do
private const string _mutexId = "MyUniqueId";
private static Mutex _mutex;
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
try
{
bool alreadyRunning = false;
try
{
Mutex.OpenExisting(_mutexId);
alreadyRunning = true;
}
catch (WaitHandleCannotBeOpenedException)
{
alreadyRunning = false;
}
catch
{
alreadyRunning = true;
}
if (alreadyRunning)
{
using (ServiceController sc = new ServiceController("MyServiceName"))
{
sc.Stop();
sc.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 120));
sc.Start();
}
return;
}
}
catch
{
}
_mutex = new Mutex(true, _mutexId);
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
// Load the service into memory.
ServiceBase.Run(ServicesToRun);
_mutex.Close();
}
You could modify your Windows Service so that it is simply a runner for your main application, and has the functionality to update your main application.
So you would have:
Service.exe: Runs Application.exe, monitors remote location for updates to Application.exe. Sends start/stop events to Application.exe
Application.exe : What used to be your Service.exe. Recieves start/stop events.

Categories