You've got a couple of options here - use Microsoft's WebHostService class, inherit WebHostService or write your own. The reason for the latter being that using Microsoft's implementation, we cannot write a generic extension method with a type parameter inheriting WebHostService since this class does not contain a parameterless constructor nor can we access the service locator.
Using WebHostService
In this example, I'm going to create a Console Application that uses Microsoft.DotNet.Web.targets, outputs an .exe and operates as a MVC app (Views, Controllers, etc). I assume that creating the Console Application, changing the targets in the .xproj and modifying the project.json to have proper publish options and copying the Views, Controllers and webroot from the standard .NET Core web app template - is trivial.
Now the essential part:
Get this package and make sure your framework in project.json file is net451 (or newer)
Make sure the content root in the entry point is properly set to the publish directory of the application .exe file and that the RunAsService() extension method is called. E.g:
public static void Main(string[] args)
{
var exePath= System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
var directoryPath = Path.GetDirectoryName(exePath);
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(directoryPath)
.UseStartup<Startup>()
.Build();
if (Debugger.IsAttached || args.Contains("--debug"))
{
host.Run();
}
else
{
host.RunAsService();
}
}
The .exe can now easily be installed using the following command
sc create MyService binPath = "FullPathToTheConsolefile.exe"
Once the service is started, the web application is hosted and successfully finds and renders its Views.
Inherit WebHostService
One major benefit of this approach is that this lets us override the OnStopping, OnStarting and OnStarted methods.
Let's assume that the following is our custom class that inherits WebHostService
internal class CustomWebHostService : WebHostService
{
public CustomWebHostService(IWebHost host) : base(host)
{
}
protected override void OnStarting(string[] args)
{
// Log
base.OnStarting(args);
}
protected override void OnStarted()
{
// More log
base.OnStarted();
}
protected override void OnStopping()
{
// Even more log
base.OnStopping();
}
}
Following the steps above, we have to write down our own extension method that runs the host using our custom class:
public static class CustomWebHostWindowsServiceExtensions
{
public static void RunAsCustomService(this IWebHost host)
{
var webHostService = new CustomWebHostService(host);
ServiceBase.Run(webHostService);
}
}
The only line that remains to be changed from the previous example of the entry point is the else statement in the end, it has to call the proper extension method
host.RunAsCustomService();
Finally, installing the service using the same steps as above.
sc create MyService binPath = "FullPathToTheConsolefile.exe"