Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running as Windows service #1386

Closed
nicolasr75 opened this issue Apr 13, 2016 · 29 comments
Closed

Running as Windows service #1386

nicolasr75 opened this issue Apr 13, 2016 · 29 comments

Comments

@nicolasr75
Copy link

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?

@davidfowl
Copy link
Member

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).

@nicolasr75
Copy link
Author

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?

@MaximRouiller
Copy link

Something similar found here:

http://taskmatics.com/blog/run-dnx-applications-windows-service/

@MaximRouiller
Copy link

I think dnx could be easily be replaced by dotnet on the cmd prompt.

@nicolasr75
Copy link
Author

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 :-(

@MaximRouiller
Copy link

MaximRouiller commented Apr 15, 2016

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"

@MaximRouiller
Copy link

If you can copy/paste what you tried and the output, we could help a bit more.

@nicolasr75
Copy link
Author

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.

@lankaapura
Copy link

Does anyone tried this with RC2? Would be great if can share a sample.

@evkw
Copy link

evkw commented May 19, 2016

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();
            }
        }
    }
}

@pfedotovsky
Copy link

@evkw Could you please provide full source code?

@ivan-prodanov
Copy link

ivan-prodanov commented May 26, 2016

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)

@Noeek
Copy link

Noeek commented Jun 8, 2016

The important key point is:

host.RunAsService();

not "host.Run();"

@guardrex
Copy link
Contributor

@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?

@davidfowl
Copy link
Member

That's not currently on the roadmap. I'd file an issue on CoreFx asking for ServiceBase to be ported over.

@guardrex
Copy link
Contributor

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

@lankaapura
Copy link

@pfedotovsky I've updated the Music Store application to run as a service and full sample available here.

Thanks @evkw for SO answer.

@gerardo-lijs
Copy link

gerardo-lijs commented Aug 28, 2016

@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.

https://github.com/gerardo-lijs/AspNetCoreWindowsService

@nicolasr75
Copy link
Author

@gerardo-lijs great example. Thanks for that! I especially like the distinction between console, debug and service.

@h3smith
Copy link

h3smith commented Sep 14, 2016

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?

@threefivedelta
Copy link

threefivedelta commented Sep 14, 2016

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/

@gerardo-lijs
Copy link

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.

@h3smith
Copy link

h3smith commented Sep 15, 2016

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?

@dasMulli
Copy link
Contributor

dasMulli commented Oct 17, 2016

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..

@PeterKottas
Copy link

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 :)

@Vladimir-Kharam
Copy link

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.WindowsService\Source\PeterKottas.DotNetCore.Example\bin\Debug\netcoreapp1.1\win10-x64>sc create PeterKottas binPath= "C:\Program Files\dotnet\dotnet.exe D:\Applications\DotNetCoreWindowService\DotNetCore.WindowsService\Source\PeterKottas.DotNetCore.Example\bin\Debug\netcoreapp1.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

  • Microsoft Windows 10 Pro
  • Visual Studio Professional 2015
    Version 14.0.25422.01 Update 3
  • Microsoft .Net Framework Version 4..6.01586
    Any help will be appreciated.

Best Regards,
Vladimir

@PeterKottas
Copy link

Hi @Vladimir-Kharam, it's best if you open an issue on my repo to keep this organized. I'll help you out there ;)

@PeterKottas
Copy link

PeterKottas commented Feb 17, 2017

And just in case somebody wants to follow, this is the issue : PeterKottas/DotNetCore.WindowsService#8
Thanks Vladimir

@aspnet-hello
Copy link

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.

@ghost ghost locked as resolved and limited conversation to collaborators Dec 4, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests