I often would like to create small, zero-configuration/installtion, self-contained, self-hosted web APIs that should run independent of IIS. On the other side they should run 24/7, independent of user logout and automatic system restarts.
What options do I have to run a self-hosted web app as a Windows service instead of a commandline app?
In RC2 there's a Windows service host https://github.com/aspnet/Hosting/tree/dev/src/Microsoft.AspNetCore.Hosting.WindowsServices. It only works on .NET Framework, not .NET Core (which is probably fine because it's windows only anyways).
Thanks David. I think I don't get how this works. I used the HelloMvc sample from cli-samples and converted it to use net461, restored, built and ran, everything works as expected.
Next I added
"Microsoft.AspNetCore.Hosting.WindowsServices": "1.0.0-*"
to project.json, restore and build work and
dotnet run
still works.
Now, how to install the service? I thought about doing
sc create MyAspNetService ....
But which executable would I use?
There was one created in
bin/Debug/net461
and another one in
bin/Debug/net461/win7-x64
Both of these cannot be started by the SCM.
Or do I have to call dotnet with parameters?
Something similar found here:
http://taskmatics.com/blog/run-dnx-applications-windows-service/
I think dnx
could be easily be replaced by dotnet
on the cmd prompt.
Thanks for the link. I tried to transfer the ideas but in the end couldn't get it to work. I list the steps I tried:
Added
Microsoft.AspNetCore.Hosting.WindowsServices
to the dependencies.
Derived the Program class from WebHostService.
At this point _dotnet restore_, _dotnet build_ and _dotnet run_ all work.
Then I did _dotnet publish_ and tried to start the exe in
bin\Debug\net461\win7-x64\publish
directly which also worked.
Then I used sc.exe create ... to register this exe as a service but the scm fails to start it with timeout.
According to the article you posted I also tried to call it via
dotnet run mypath
or
dotnet mypath run
but that doesn't work either because dotnet does not seem to understand a path parameter.
At that point I ran out of ideas :-(
Is dotnet
in your global path?
The actual command should be something like this :
sc.exe create MyService binPath= "C:\path\to\dotnet ""C:\path\to\my\project\folder"" run"
Another example I found was something like this:
sc.exe create "My Self-hosted Website" binPath= "C:\Users\YOUR_USER_NAME\.dnx\runtimes\dnx-clr-win-x86.1.0.0-rc2-16357\bin\dnx.exe -p C:\YOUR_DIRECTORY\WWWService\ run --windows-service"
If you can copy/paste what you tried and the output, we could help a bit more.
Here is what I did.
I modified HelloMvc sligthly, see the following project.json and Program.cs
{
"content": [
"wwwroot",
"Views",
"web.config"
],
"compilationOptions": {
"preserveCompilationContext": true,
"emitEntryPoint": true
},
"dependencies" : {
"Microsoft.AspNetCore.Diagnostics": "1.0.0-*",
"Microsoft.AspNetCore.Mvc": "1.0.0-*",
"Microsoft.AspNetCore.Server.Kestrel": "1.0.0-*",
"Microsoft.AspNetCore.StaticFiles": "1.0.0-*",
"Microsoft.AspNetCore.Hosting.WindowsServices": "1.0.0-*",
"Microsoft.Extensions.Logging.Console": "1.0.0-*",
"Microsoft.NETCore.Platforms": "1.0.1-*",
"System.Runtime.Serialization.Primitives": "4.1.1-*"
},
"frameworks": {
"net461": { }
}
}
using System.IO;
using System.Diagnostics;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.WindowsServices;
namespace HelloMvc
{
public class Program : WebHostService
{
private readonly EventLog _log =
new EventLog("Application") { Source = "Application" };
public Program(IWebHost host) : base(host)
{
_log.WriteEntry("Test from my Asp.net service.", EventLogEntryType.Information, 1);
}
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseDefaultHostingConfiguration(args)
//.UseIISIntegration()
.UseStartup<Startup>()
.Build();
host.Run();
}
protected override void OnStarting(string[] args)
{
_log.WriteEntry("Asp.net service starting.");
}
protected override void OnStarted()
{
_log.WriteEntry("Asp.net service started.");
}
}
}
_dotnet restore_, _dotnet build_ and _dotnet run_ work.
Then I did _dotnet publish_ to create a self-contained package that I transferred to a test computer. On that test computer dotnet is installed and returns the following information
.NET Command Line Tools (1.0.0-rc2-002395)
Product Information:
Version: 1.0.0-rc2-002395
Commit Sha: c83a2fb6f9
Runtime Environment:
OS Name: Windows
OS Version: 10.0.10586
OS Platform: Windows
RID: win10-x64
Navigated into the publish directory and did
C:\Users\Public\Documents\dotnet>HelloMvc.exe
Output is
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[3]
Hosting starting
dbug: Microsoft.AspNetCore.Hosting.Internal.WebHost[4]
Hosting started
Hosting environment: Production
Content root path: c:\Users\Public\Documents\dotnet
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
So this works as expected. Now I tried to register this HelloMvc.exe as a service with
C:\WINDOWS\system32>sc create AspNetTestService binPath= "C:\Users\Public\Documents\dotnet\HelloMvc.exe"
[SC] CreateService SUCCESS
Trying to start it fails:
C:\WINDOWS\system32>sc start aspnettestservice
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
The Windows Event Log shows
A timeout was reached (60000 milliseconds) while waiting for the AspNetTestService service to connect.
Should I really try to increase the timeout and test again? I think I really misunderstand how it's supposed to work.
I will try your suggestions now.
Does anyone tried this with RC2? Would be great if can share a sample.
Ive got a service running with something that looks like below. Using net451 framework though.
My service takes in a config.json however and because services run from System32, if the config.json file is not there, it fails.
Havent figured out how to make the service look for files in the executables path
using System;
using System.Diagnostics;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.WindowsServices;
namespace Service1
{
public class Program
{
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
if (Debugger.IsAttached)
{
host.Run();
}
else
{
host.RunAsService();
}
}
}
}
@evkw Could you please provide full source code?
Guys, I just wrote an answer at StackOverflow about this. I got a console app running as a website app hosted as a windows service (sounds cozy I know)
The important key point is:
host.RunAsService();
not "host.Run();"
@davidfowl @DamianEdwards @shanselman
... works on .NET Framework, not .NET Core (which is probably fine because it's windows only anyways).
... except that Nano Server can't do that. Will .NET Core get a Windows Service capability (for Nano) eventually?
That's not currently on the roadmap. I'd file an issue on CoreFx asking for ServiceBase to be ported over.
Ok, thanks. Will do. In the meantime, I'm looking at a GPO startup script to fire up a console app. https://technet.microsoft.com/en-us/library/cc770556(v=ws.11).aspx
@pfedotovsky I've updated the Music Store application to run as a service and full sample available here.
Thanks @evkw for SO answer.
@nicolasr75 I was needing exactly the type of project you were asking for and the good news is that it's really simple now with ASP.NET Core 1.0 using Microsoft.AspNetCore.Hosting.WindowsServices dependency.
I created a bare minimum sample repo to demonstrate it and from there it would be really simple to copy/paste to your current API or MVC project.
@gerardo-lijs great example. Thanks for that! I especially like the distinction between console, debug and service.
Is there a path (or what is the path) to build a "service" that is cross platform?
ie: We have an old .NET 4.5 Windows service that performs background tasks (emails, notifications, etc).
We'd want to bring this to .NET Core and run it in Docker - but the question is what is the best approach? Is it along the lines of @gerardo-lijs? But, how are long running tasks defined and managed if we went the Kestrel route?
Without knowing a lot about what you're trying to accomplish, how helpful do you find the following information after you've had a chance to try it out?
Let me know.
Doug Timpe
Windows Insider
http://www.howtogeek.com/50786/using-srvstart-to-run-any-application-as-a-windows-service/
Hi @h3smith, without know the specifics of your service, I would say generally speaking that if you want to run some .NET code that provides some services in Linux, Mac or Windows you have to target the .Net Core Framework and probably the best path will be to provide some sort of Web API using JSON to interact with it. Long running background task is kind of specific to Windows Services. When using Web API, probably you will refactor some of your code to work in a more disconnected kind of way. Probably in your case, it would be better to use nginx to access your API and manage SSL security instead of Kestrel.
Gents, thanks for the input. Use case so far is simple. We have a Windows Service (.NET 4.5) that sits and polls our database every 1-10 seconds (depends on settings) to see if there are emails or push notifications to send out.
We'd like to get this on .NET Core, obviously as soon as we can.
I guess the real question is, (I know we can't be the only folk with services like that), what is the best guidance? Our end goal is to drop this in Docker and make it incredibly easy to configure and deploy.
So, obviously Windows is seemingly easy - deploy it as a Windows Service, but trying to be platform independent there doesn't seem to be clear guidance or direction to take.
(But must say, we've migrated the rest of our stack to .NET Core and, just amazing job and love it all)
Edit: I guess the real concern is, let assume we deploy it as just a CLI tool that we deploy in Docker, how do we ensure it stays up and running? Windows services is cake as you just have it attempt to restart. Can this be accomplished with using an MVC site and something like Hangfire.IO?
So.. been desperatly wanting to run as Windows Service on .NET Core myself. So i ended up implementing a ServiceBase-like hosting lib. Even added functions to register and unregister as windows service. Until there is a ServiceBase for .NET Core, i can't really find another "good" way. If someone is blocked on this and/or wants to give it a try, i published it on NuGet as DasMulli.Win32.ServiceUtils
(1.0.1
). Look at / follow the examples linked from the README at https://github.com/dasMulli/dotnet-win32-service. Always appreciate feedback.
It does work on nano server 馃槃
But if you want to run as docker container, there isn't really a need for a windows service as you can just set the container's startup command to dotnet C:\path\to\MyApp.dll
and then you can control it via docker start
and docker stop
..
Hello everybody, I found this topic while looking for a solution to a similar problem. Ended up implementing something that works pretty much like very (very) simplified Topshelf. You can easily run as console and/or install, uninstall and so one as a service. I think it can be pretty useful for somebody. You can find the code here : https://github.com/PeterKottas/DotNetCore.WindowsService and there's nuget here as well https://www.nuget.org/packages/PeterKottas.DotNetCore.WindowsService/ . Enjoy :)
Hello All. I have found the post of Peter Kottas very interested. I have installed the tool. The example service is working properly as console application. I can also successfully create window service using following command in administrator mode:
D:Applications\DotNetCoreWindowService\DotNetCore.WindowsServiceSource\PeterKottas.DotNetCore.Example\bin\Debugnetcoreapp1.1\win10-x64>sc create PeterKottas binPath= "C:\Program Filesdotnetdotnet.exe D:Applications\DotNetCoreWindowService\DotNetCore.WindowsServiceSource\PeterKottas.DotNetCore.Example\bin\Debugnetcoreapp1.1\win10-x64\PeterKottas.DotNetCore.Example.dll --run-as-service"
[SC] CreateService SUCCESS
When I am trying run the service by command
sc start PeterKottas (Administrator Mode)
I have the following error:
[SC] StartService FAILED 1053:
The service did not respond to the start or control request in a timely fashion.
My working environment
Best Regards,
Vladimir
Hi @Vladimir-Kharam, it's best if you open an issue on my repo to keep this organized. I'll help you out there ;)
And just in case somebody wants to follow, this is the issue : https://github.com/PeterKottas/DotNetCore.WindowsService/issues/8
Thanks Vladimir
This issue is being closed because it has not been updated in 3 months.
We apologize if this causes any inconvenience. We ask that if you are still encountering this issue, please log a new issue with updated information and we will investigate.
Most helpful comment
Guys, I just wrote an answer at StackOverflow about this. I got a console app running as a website app hosted as a windows service (sounds cozy I know)