How to properly program a windows service? - c#

I've been having some fun reading about windows services on MSDN, but i'm having some trouble grasping some of the information.
I have created a windows service following the steps at this msdn page, and i noticed that they ommitted that one of the automatically generated sections (namely, the main section in program.cs) starts a collection of services. I'm having trouble understanding how will a service actually run, or more correctly, how do i correctly program a service to do what i want. The automatically generated service.cs only has a constructor, an an OnStart and OnStop event methods. Should i program the bulk of my code on the OnStart method, or is there a similar Main section to services?
Another question i have is regarding the deployment of services. At the page i mentioned, they referenced another page that has me use installutil on the VS developer console. How can i make an automatic installer for the service, in case the target platform doesn't have the developer console?

A service is no more than a (most of the time) console program. So, yes, the OnStart method is the entry point for your service, just like the Main method. If your service has to be executed periodically, you have to manage the loop part. The OnStop method is called whenever the user manually stops the service or when the system does.
The reason there is a ServiceBase array launched in the Main Program method, is that you can have multiple service classes and launch them in parallel.
You have to know that the content of the Main method can only be executed by the system in the context of an installed service. You cannot debug this way. You have to do it using a classic "console app". I personally use a trick to debug a service in VisualStudio more easily:
Let say we have an ImportService class that do our processing. We will use DEBUG compiler constant and create a DebugStart() method that will start processing (OnStart method is protected)
#if DEBUG
public void DebugStart()
{
// Call you processing method
}
#endif
Now let's edit our Main() Program method the same way to start our processing instead of the ServiceBase.Run method when debugging:
#if DEBUG
ImportService service = new ImportService();
service.DebugStart();
#else
ServiceBase[] ServicesToRun =
{
new ImportService()
};
ServiceBase.Run(ServicesToRun);
#endif
This way, when running your project in debug mode it will launch the service as a standard console program.
The installutil command is a windows command used to install a service program. To install your service, you have multiple solutions, depending on your installer:
Using InstallShield. Since Visual Studio 2013 (or maybe 2012?), InstallShield Lite Edition is standardly included in place of former Windows Installer. You have to activate and install it though (Create a new project of Other types>Configuration and deployment>Activate InstallShield Limited Edition). You can install windows services with it in the form of an installer
Making a simple .bat file that will run the installutil command on the client machine.
Using WiX which is very complete but also more complex but allows you to do anything during installation.

How can i make an automatic installer for the service, in case the target platform doesn't have the developer console?
You have to add a System.Configuration.Install.Installer to install your service on a remote machine. This should even work if the target machine doesn't have the developer console available.
I'm having trouble understanding how will a service actually run, or
more correctly, how do i correctly program a service to do what i
want.
That's actually a lot simpler than you might initially think. Your service will run the same as it would if it was a normal process. If you have a console application that opens a port and listens for traffic, then that would still work pretty much in the same way when you turn it into a service.
What does change, however, is how your service is started. After you have installed your service properly, you can start it like this:
[MTAThread]
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new YourServerClass()
};
ServiceBase.Run(ServicesToRun);
}
YourServerClass should inherit ServiceBase, which will allow you to use the OnStart, OnStop methods. In those methods you specify how your service is started, and what should be done (in terms of cleanup etc.) when your service is stopped.
If all went well, and you have the installetr and the actual service in the project, you should be able to install it as a service through the use of PowerShell, after which you can just start, stop and restart it from the Services window as you would with any other service.

Related

Updating and restarting the current running Windows Service in C#

I have a .NET 6 application compiled as a standalone executable that runs as a Windows service. What I want to add is a way to update and restart the service when it detects that a new version is available. The problem is that I can't find a way to actually restart a service with a single command in a way that can be triggered from C#.
The sc.exe can be used to create, modify, start and stop a service. But it does not have a restart command. My original plan was to modify the service and point it to the new binary, and then restart it using sc.exe, but then I noticed that it doesn't actually have a real restart command.
The Powershell cmdlet Restart-Service does what I want, but the C# Powershell integration seems to have some severe issues and bugs when the C# application is compiled as a standalone executable. It simply does not work at all for me.
I'm triggering the update from the running Windows service itself, so I can't just execute a stop command and then try to execute the start command, as my application won't be running anymore at that point.
One option might be to execute both sc.exe stop and sc.exe start in a way that isn't interrupted when the calling process is stopped, but I'm not sure which method would work reliably here. Another idea would be to slightly misuse the auto-restart on failure mechanism for Windows services. But I'm not sure I can trigger that without creating superfluous error messages in the Windows Event logs.
What options do I have to reliably restart a running Windows service from the running C# application itself?

Windows services does not run my class method

I have a windows service application which would scan the wifi list and save to file. then i will read the file and write to mysql database and close the file. my wifi scanning and db methods in another class within same windows service project which i invoke in service class. I am able to run and install the windows service but i think those methods are not called. I have even tried them in the service class but they still didn't call up in OnStart method. When i run it section mode and debug from visual studio it works fine but when i install it in installutil it only starts the service nothing happens though the service still runs in the background. I've created windows form version of this and that works fine.
I think it's more likely that the class method is called but writing the output file fails. The account that is used to run the service likely has no rights to create and/or write the output file. Check the folder that it should be written to and see if the account that runs your service has proper access rights. You can also use Process Monitor to verify this (set a filter on Path or Process Name).

Running a C# console application as a Windows service

I have a basic C# console application that I would like to run as a Windows Service.
I have created the Windows service using sc create. This worked fine, and I can see my service under services.msc. When I try and start this service I get the following error:
Could not start the PROJECT service on Local Computer. Error 1053: The service did not respond to the start or control request in a timely fashion.`
I read that this might be due to the service code taking longer than 30000 ms to execute. Therefore I removed the bulk of the code so that hardly anything is being executed.. yet the same error persists.
I am using .NET 3.5 for this project.
What would cause this?
You cannot just take any console application and run as Windows service. First you need to implement your service class that would inherit from ServiceBase, then in entry point (Main) you need to run the service with ServiceBase.Run(new YourService()). In your service class you need to define what happens when service starts and ends.
Ideally you should add ServiceInstaller to your assembly too. This way you will be able to preset your service properties, and use installutil.exe to install the service.
Walkthrough: Creating a Windows Service Application in the Component Designer is a walkthrough of how to create a service.
Not any old application can be run as a service, especially under more recent versions of Windows. They are expected to support certain functionality, respond to certain requests, and (again, under recent versions of Windows) not interact with the user directly.
If you want a service, write an application specifically designed to be a service.
I do not know what "sc create" is. But I know, using Visual Studio 2010, one can build a Windows service project. By the way, I have created a project of this kind and it does work well all the way.
why is this so? – wulfgar.pro Jun 3 '11 at 1:13
#WulfgarPro - because windows service application has a little
different architecture. You need to define what to do when service starts and ends. – Alex Aza Jun 3 '11 at 1:15
(Unfortunately I can't write a comment yet.)
It is because SCM (Service Control Manager) controls the service trough ServiceBase Class. If one would only need to define what it does when it starts and stops there would be no need for inheritance and overriding. One could simply create those two methods. Unfortunately there is a bit more work involved because ServiceBase contains a bit more functionality.
I have had great success with TopShelf. This is a nuget package that allows your .NET console app to also have the necessary Windows Service hooks such that it can happily run as either a console app (useful for debugging), or be installed as a Windows Service.

Testing Windows Service in .Net

I'm developing a windows service in C# .Net and i'm having some dificulty to execute and test my service.
I'm using a timer component to run it from time to time and execute my methods. I have to intialize the service all the time to run it.
Anyone know a more practical way to test a service?
This often boils down to the question what you want to test. Do you want to test the service, or the functionality that it performs? Personally I would...
Refactor all of the service functionality into a separate class library
Test the library
Invoke the library functionality from the service
...and then keep the amount of code in the service itself to the bare minimum needed to trigger the functionality in the class library.
Windows services are ordinary EXEs that happen to connect to the service control manager on startup.
I normally test services by giving them an optional command line argument that tells them to execute normally, inside the Main method, instead of acting as a service. That way I can debug them directly within Visual Studio, or on the command line, etc.
You probably want to add unit tests to your service.
It sounds like you could benefit more from adding your application to the Task Scheduler instead of running it as a service.
Other than that if you really need it as a service you need to design it so it can be tested. I usually write my services in a separate class and add a .EXE project to it so I can run it from the command line too.
One of the ways I have run services when developing is along these lines - Run a windows service as a console. I have found it useful because you can add code to write out to the console for debug information and writing out any relevant exception data.
I would not use this method instead of unit tests but I found this to be a useful way to work and debug where needed.
After create window service you can set it into window service.
Install service using InstallUtil.exe
To install or uninstall windows service (which was created using .NET Framework) use utility InstallUtil.exe. This tool can be found in the following path (use appropriate framework version number).
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe
To install .NET service run command similar to this (specify full path to your service).
InstallUtil.exe "path of service"
To uninstall .NET service use the same command with parameter /u.
InstallUtil.exe /u "path of service"

Multiple Windows Services, One Installer, Removing Dependencies

I have a single service installer project that installs multiple services. This is great but a single unhandled exception in any single service will stop all services that were installed by this installer.
The code for the installer looks something like this
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1() ,
new Service2() ,
...
};
ServiceBase.Run(ServicesToRun);
So once the service is installed I can see several separate services in the windows service management window and each can be started, stopped, paused, resumed independently.
However if one suffers an unhandled exception then they all stop.
Ideally only the service that had the problem would stop and the other services would continue on their merry way.
Can anyone suggest a way to do this without creating a truly separate installer project for each service?
Add independent error handling per service at the highest level, this way not all of the services will be effected.
You may also want to add a auto service restart if the error is not critical. Just be sure you add tons of logging in the case of service shut downs and restarts from errors.

Categories