Testing a Windows Service Project takes too long - c#

I have here a Windos Service Project in Visual Studio and because you cannot start a service without installing it, I have to compile + uninstall old service + install new service again and again if I want to test some changes on my code. This is taking forever.
Is there no easier way to test windows services? Thank you

Run the service from VS as a console application. In fact, if you are smart, you can test whether
Environment.UserInteractive
This way with a simple "if" you can have your service running normally, without the windows service stuff if you run it in an interactive mode or, if it is run as a service, you perform a normal service startup.

When testing services, I would usually recommend to separate the functionality from the hosting. And test the functionality in an independent manner.
What this means is the your probably spawns a worker thread in OnStart, and this thread instantiates and calls some class methods that represent the actual workings of the service. Technically, this piece of logic should not explicitly care where it runs, console app, windows service or a web service etc..
I I would advise you to test this logic directly, for example in unit tests, where the logic is hosted by visual studio itself. This is not to suggest you should not test the service, but this can be done manually or automatically, especially during QA or Sanity testing, where it is OK to run tests that take a long time to execute.

Related

Testing/using a WCF service from Jenkins

The core of our system requires a WCF service to be either installed or launched in interactive mode. The latter is currently the preferred way for debugging purposes.
The problem I am having is that I would like to run regressions from Jenkins that require that service to be up and running first.
The service must first be built (C# solution) and cannot reside on the test machine, since its implementation may change over time.
I could add pre and post steps in my Jenkins pipeline to install/remove or launch/kill the service, but it is very messy and requires every single job to do the exact same thing (which could be omitted and result in having a residual installed/running service preventing any future job to run).
Is that the way to do it or are there other approaches for it?
Another issue in interactive mode is to keep the console (running the service) going for the time of the test (which is a separate process).
Say we started the service in interactive mode ; it would end up terminating before any test gets the chance to run.
What would be the way to keep the service running for the duration of the test only?

Difference between a console application and Web application in asp.net core

I am trying to run a background service which just writes to a file on a specified interval.
There are two methods that I tried
1) Created the project with the Console application template
2) Created the project with Web Application as template
When I run the app from visual Studio, both of them run fine. But when I deploy them to IIS, only the web application version works. It must be noted that there is absolutely no difference between the code of the two projects. I have used the WebHost as a hosting strategy in both the projects as well as well as installed all the dependencies in case of Console application as there are in the Web Application version.
I must also inform that I have used the preloadEnabled="true" option in IIS as IIS needs a web request to start the application.
I am wondering what is the difference between both the project types as the code is the same? I don't want the Web Application template.
Edit 1: I forgot to mention that the service will also need to expose an api endpoint for healthcheck purposes. Will the windows service approach listen for http requests?
I used the following article for implementing my background service.
https://learn.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice
After years of building background services, I learned that Windows services are the best tools to implement these applications. While there are different techniques to keep an IIS application up and running in the background and prevent it from getting recycled, in practice, the applications on IIS are not meant to be executed forever.
If you had an intention to build your app in the cloud, I would have suggested using something like Azure WebJobs or Azure Functions Timer-Triggered functions, but for on-premise, even using something like Hangfire in the web is not sustainable. The worst happens when you need backward compatibility on Windows servers that don't have the "Application Initialization" module.
My suggestion is to move your application to a simple Windows Service if you control your environment. Windows services consume less memory, are easier to manage, and can run forever without getting recycled.
WebApplications are plain the wrong tools for this.
Being always on and always reachable, WebServers are primary targets for hacking. To compensate for that, they are usually run under the most restrictive user rights you can imagine: Read rights to their programm and this instances content directory. While I do not know why it worked at all, it propably will stop working in Production.
What you wanted to write was eitehr a Service or something executed by the Windows Task Sheduler. Personally I advise for the Task Sheduler as Services have their own set of restrictions. Unless of coruse there is some detail of the requirements that you did not told us.
This article could be helpful. It's a step by step tutorial on how to convert a console application to a web application.

How can I run my WCF Service Library "in process"

I have a WCF CRUD REST API up and running in a Windows Service. All is well.
I'd like to offer the user the ability to run that inprocess as well; so, instead of running a service (which would require admin) I'd like to have a static library version as well.
With .NET (C#) how would I go about this? Right now I have:
ServiceLib (interesting code)
ConsoleHost
GUI
I'd like the GUI to selectively be able to run the ServiceLib code as a full-fledged Windows Service -OR- just as in-process code. The service way already works, which I assume is harder.
If you run it now in a Windows service it's already self-hosting, I assume? If GUI app will be the only one using the service in the "in process" mode you can split your "WCF CRUD REST API" ServiceLib into two - one implementing CRUD part and second implementing WCF REST API on top of it. In GUI you'll need only the CRUD part, so no need to bother with self-hosting of REST API in the same (and only) application that's going to call it.
Running a GUI app as a Windows service is usually a pretty bad idea anyway from the sysadmin's point of view. I often run console apps that can be either WCF hosting Windows services or just WCF hosts, but their only GUI is ablility to react to Ctrl-C.

Windows Service doesn't start after installation

I have built one windows service that sends out email after every 30 minutes in C#. The Service start mode is set to Automatic. But still windows doesn't start automatic. I need to manually start by going to Services.msc and right clicking the service and select start
When the StartMode is set to automatic, that just means that it will start up when Windows boots up.
You can start the service yourself in a custom action in your installer. I assume you have an Installer class already and that it is already a custom action for your setup project since the service is installing, but not starting.
Override the OnAfterInstall method in the Installer class you have and you can start the service like this:
protected override void OnAfterInstall(IDictionary savedState) {
base.OnAfterInstall(savedState);
ServiceController sc = new ServiceController(“MyServiceName”);
sc.Start();
}
However, a scheduled task is not a bad way to go.
Why put yourself through all the overhead and suffering of troubleshooting and maintaining a windows service for a time based/polling application? The windows OS has built in support for this. Just create a simple console application. Run it as a scheduled task.
You should already have unit tests and decoupling to make the code unit-testable. If you don't your troubleshooting is overly difficult. Once you have your code in this unit-testable format flipping to a console app is a no brainer.
I knew a guy who made everything a windows service and labeled it SOA. Piling up windows services for polling/time based mechanisms isn't SOA. Its so sloppy compared to console applications and so much more difficult to maintain I can't even begin to express how bad an idea it is. I had to deal with about ~20-30 of these win services and once they were converted to n-tier and a console app suddenly the stability of the application went through the roof and my life got 10x easier. So please, do yourself a favor and listen to somebody who has been through months and many iterations of these types of app. Run it as a scheduled task in a console app.
Auto-starting services are subject to problems with service initialization order. You have plenty of dependencies, the TCP/IP stack better be in working order before you try to send an email, for example. Look in the Windows event log for an exception message that prevented OnStart() from getting the service started.
This can be configured for a service, check out the Dependencies tab for the Print Spooler service for example. This is however difficult to deal with, hard to figure out exactly which services need to be running and hard to write the registry entries that configure the dependencies.
Punt the problem: don't send an email message right away. Wait a while, 30 minutes for example.
You install it with installutil? You're right, it doesn't start the service, even if it's set to automatic. If I were you, I'd provide a batch file which calls installutil and then also runs 'net start whatever'. Or if you're using other kinds of installation, those should provide this ability too.

C# ClickOnce deployment for Windows Services?

What are some best practices for being able to deploy a Windows service that will have to be updated?
I have a Windows service that I will be deploying but might require some debugging and new versions during the beta process. What is the best way to handle that? Ideally, I'd like to find a ClickOnce-style deployment solution for Windows services but my understanding is that this does not exist. What is the closest I can get to ClickOnce for a Windows service?
A simple solution that I use is to merely stop the service and x-copy the files from my bin folder into the service folder.
A batch file to stop the service then copy the files should be easy to throw together.
Net stop myService
xcopy \\myServerWithFiles\*.* c:\WhereverTheServiceFilesAre
net start myService
I have a system we use at work here that seems to function pretty well with services. Our deployed system has around 20-30 services at any given time. At work we use a product called TopShelf you can find it here http://topshelf-project.com/
Basically TopShelf handles a lot of the service related stuff. Installing, Uninstalling etc all from the cmd line of the service. One of the very useful features is the ability to run as console for debugging. You build one service, and with a different cmd line start you can run it as a console to see the output of the service. We added one custom feature to this software that lets us configure profiles in advance. Basically our profiles configure a few things like logging, resource locations etc so that we can control all that without having to republish any code. All we do is run a command like
D:\Services\ServiceName.exe Core.Profiles.Debug or
D:\Services\ServiceName.exe Core.Profiles.Production
to get different logging configurations.
Our build script creates install.cmd and uninstall.cmd scripts for each of our services all we do is copy the files to the server and run the script. If we want to see debug output we stop the service and double click the exe and we get a console to read all the output.
One more thing that topshelf has which we don't use because its not necessary is the concept of shelving (there is documentation on this website for this). This allows you to update the service without having to "restart" but you still need to copy the files manually unless you build an automated system for that.
However, my suggestion if you need 100% service availability is to have a redundant system. No matter how you configure your service for updates you cannot avoid hardware failure causing downtime without an automated failover system. If said system was in place my recommended update strategy would be to turn off 1 node, update, test, turn on turn off the other node, update, test and turn the 2nd node back on. You can do this all of course with a simple script. This may be a more complicated system than you need but if you can't take a service offline for a simple restart that takes 5 seconds then you really need some system in place to deal with hardware issues because I can guarantee it will happen eventually.
Since a service is long-running anyway, using ClickOnce style deployment might not be viable - because ClickOnce only updates when you launch the app. A service will typically only be launched when the machine is rebooted.
If you need automatic update of a service then your best bet might be to hand-code something into the service, but I'd forsee problems with almost any solution: most install processes will require some level of user interaction (if only to get around UAC), so I can't imagine this would lead an answer that doesn't involve getting a logged-on user in front of the screen at some point.
One idea that might just work is active-directory deployment (or some similar equivalent). If your service is deployed via a standard MSI-type installer, AD allows you to update the application silently as part of the computer policy. I suspect you'd have to force the server to refresh the AD policy (by rebooting or using gpupdate from the console), but other than that it should be a hands-off deployment.
I would suggest using the "plugin" approach on this, that is, using the Proxy Design Pattern.
While using this pattern, an independant thread may verify over a folder for updates. You will need to use ShadowCopy over your assembly deployment. When your service update-thread encounters a new version of your service, it shall unload the current production assembly and load the new version, without stopping the service itself. Even more! Your service should never notice the difference, if there is no breaking code within your assembly.
I would suggest to create a normal setup project, and add the windows service project output in that setup project.
For more information please refer to http://support.microsoft.com/kb/816169.

Categories

Resources