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"
Related
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.
I'm struggling with starting a service from another application.
Ok, first, that's my starting point:
I got a usual service wrapped into my own class which inherits from ServiceBase.
Furthermore I got a ProjectInstaller instance, which inherits from System.Configuration.Install.Installer and takes care of installing my service on the system in the right way.
it's got these parameters:
serviceInstaller1.ServiceName = "NameOfService";
serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Manual;
serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
This ProjectInstaller output is installed through a usual C# .NET installation project.
The service is shown in the GUI list of services within system control -> administration -> services. But what I'm wondering about is that the service does not appear in the list of services, if I use the cmd.exe and type "net start".
That's waht I have so far.
Now I want to start my service from another application. This application inherits from
ServiceController
If I want to call now the
Start()
method, I get an error telling me that the service could not be opened of the local machine.
I use the same Service Name as stated above. T'm confused about that, because I thought the service is installed correctly through my installer.
Or does my application (and the cmd.exe too) does not have enough rights to access the service?
I found this article on stackoverflow.
I think this answer posted there can be applied here too.
see the link below
ServiceController permissions in Windows 7
I've run into this issue before, and it was permissions-based for me, too. I wish that error message was a little more clear.
I'd recommend taking a look at this SO article: C#.NET: Acquire administrator rights? - it looks like there's a good tutorial about upgrading to administrative rights provided in the answers.
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.
I need to create many windows services to host many WCF Service so I can stop a single one (for example to update it) and keep the other running.
Since I don't want to create a windows service for every WCF Service I have, I'm trying to create a C# application that can register itself as a windows service but with different parameters (and service name of course).
For example calling it this way:
MyService.exe /install WcfService1.dll
MyService.exe /install WcfService2.dll
This creates two different windows service like these:
WcfService1 -> MyService.exe /run WcfService1.dll
WcfService2 -> MyService.exe /run WcfService2.dll
I can't find a way to do this other than editing directly the registry.
I've found a nicer way to do it: sc.exe
sc.exe create WcfService1 binPath= "MyService.exe /run WcfService1.dll"
so I just need to create a bat/cmd to launch this command.
By its nature, a service is designed to be the go-to process for dealing with a particular thing, and having multiple instances is generally not a good idea. However, it is possible to do what you want; for instance, you can have multiple instances of SQL Server running at one time.
Have a read of this. Basically, your service installer can be given some command-line or other configurable argument that will tell it the name to which it should register itself in Windows as a service. This is normally automatic based on the service installer's and service executable's properties, but all of this can be set dynamically as well. Change the name, and you change the service registration. The name of the service should be (AFAIK) inspectable by the executable being run as the service, which can tell it the WCF service for which it is responsible.
I have a C# Windows application which runs a service. I would like to leverage PowerShell in order to offer a command line management interface for administering my running service.
From my point of view, I am trying to offer the same administrative interface a la Exchange 2007.
Do you have any suggestion or sample code on how to start/design the management cmdlets in order "connect" to the running service to query or send administrative commands?
How can I access service's internal runtime state from powershell command line? For example I would like to implement a cmdlet called Get-ConnectionsInfo to find out how many outbound connections my Windows service is using when the cmdlet is executed.
A practical example or web link to an example would be more than welcomed.
Thanks,
Robert
A solution would be for your Windows Service to expose an administrative interface through WCF. Your PowerShell commands would use this WCF service to pull out information and make the Windows Service perform actions.
The key here is to start by writting an API that you can access from .Net, then you can easily wrap the calls to this API into a DLL that exposes classes that are PowerShell cmdlets. If you want someone to be able to administer your service remotely then I think probably the best thing is to create either a webservice or WCF Service that does this and then you can wrap that in PowerShell. If you have a look on codeplex you will find some examples of administer remote web based services like GoGrid and SQL Data Services that will give you some sample code to get you started.
Another way of exposing the internal state of the Windows Service came to mind. You could expose information through WMI which can be consumed from PowerShell or your PowerShell commands.
I'm not sure if you are able to tell your service to perform actions through WMI but you would at least be able to pull out state.
A third alternative might be to make the Windows Service be a PowerShell content provider. However I have never made one myself so I'm not sure if they're suitable for hosting in a Windows Service, since the service might not be running all the time.