【问题标题】:How to start a AspNetCore App from an existing windows service如何从现有的 Windows 服务启动 AspNetCore 应用程序
【发布时间】:2018-08-23 15:33:31
【问题描述】:

我有一个现有的 Windows 服务。目标是拥有一个 REST 接口来与此服务进行通信。我认为只制作一个 ASP.NET Core Web 应用程序(参见屏幕截图)并在我现有的服务中启动整个事情可能是一个好主意。然后他们可以共享同一个 IOC 容器等等。

然后我用sc create s1 binPath = "pathgoeshere"注册了服务

当我启动服务(附加到进程以进行调试)时,输出窗口中出现错误:

Exception thrown: 'System.DllNotFoundException' in Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll
The thread 0x5250 has exited with code 0 (0x0).
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
'WindowsService1.exe' (CLR v4.0.30319: WindowsService1.exe): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\System.ServiceProcess.resources\v4.0_4.0.0.0_de_b03f5f7f11d50a3a\System.ServiceProcess.resources.dll'. Module was built without symbols.
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
The thread 0x4fa0 has exited with code 0 (0x0).
Microsoft.AspNetCore.Server.Kestrel: Warning: Unable to bind to http://localhost:5000 on the IPv4 loopback interface: 'Die DLL "libuv": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.'.
Exception thrown: 'System.DllNotFoundException' in Microsoft.AspNetCore.Server.Kestrel.Transport.Libuv.dll
The thread 0x58c4 has exited with code 0 (0x0).
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Exception thrown: 'System.DllNotFoundException' in mscorlib.dll
Microsoft.AspNetCore.Server.Kestrel: Warning: Unable to bind to http://localhost:5000 on the IPv6 loopback interface: 'Die DLL "libuv": Das angegebene Modul wurde nicht gefunden. (Ausnahme von HRESULT: 0x8007007E) kann nicht geladen werden.'.
Exception thrown: 'System.IO.IOException' in Microsoft.AspNetCore.Server.Kestrel.Core.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Exception thrown: 'System.IO.IOException' in mscorlib.dll
Microsoft.AspNetCore.Server.Kestrel: Critical: Unable to start Kestrel.

我把整个例子放在了 GitHub 上:

https://github.com/SuperSludge/aspnetcoreService

有人做过这样的事吗?我完全走错了路吗?将整个 Windows 服务重写为 ASP.NET Core App 是否更容易?

【问题讨论】:

  • 看来您的方法应该可行。您是否查看过 Windows 服务文档中的 Host ASP.NET Core? docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…
  • @ShaunLuttin 是的,我看过这个。问题是我有2个项目。一个现有的 Windows 服务和一个新的 Rest API 项目。正如我所提到的,如果我能够获得 Asp.NET 核心 API 的所有好处,但将其托管在现有项目中,那就太好了。否则我将不得不安装、注册、维护 2 个 Windows 服务。或者(正如我提到的)在 ASP.NET 核心应用程序中重写整个服务。

标签: c# asp.net-core windows-services


【解决方案1】:
Do you need ASP.NET core application or just expose REST endpoints ? I am thinking you are trying to use it for the benefits of the library. If latter is true,   
 I have done a similar thing where we have exposed some REST endpoints hosted in our legacy Windows service through "Microsoft.Owin.Hosting". This looks exactly like the ASP.NET WEPAPI

    1) In your windows service, you can start the WebApp like

           //WEBAPI URL
           private const string WEBAPI_BASEADDRESS = "https://+:{port number}/";
           // declare a Idisposable variable
           private IDisposable webAPI;
           //Use Microsoft Owin's library to start it up
           webAPI = WebApp.Start<Startup>(url: WEBAPI_BASEADDRESS);

    //above "Startup" is a class you would declare in your other class library (see below number 2)


    2) You can create a new C# class library with a class named "Startup"  and use the system.Web.Http "Httpconfiguration" class as below

    /// <summary>
    /// Web API startup method
    /// </summary>
    public class Startup
    {
        private const string TOKEN_URL = "/api/token";
        private const string BASE_URL = "/api/{controller}/{id}";
        // This code configures Web API. The Startup class is specified as a type
        // parameter in the WebApp.Start method.
        public void Configuration(IAppBuilder appBuilder)
        {

            // Configure Web API for self-host. 
            HttpConfiguration config = new HttpConfiguration();
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: BASE_URL,
                defaults: new { id = RouteParameter.Optional }
            );

            appBuilder.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString(TOKEN_URL),
                Provider = new CustomAuthorizationServerProvider()
            });
            appBuilder.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

            //Swagger support
            SwaggerConfig.Register(config);
            //appBuilder.UseCors(CorsOptions.AllowAll);
            appBuilder.UseWebApi(config);
        }
    }

    3) Above code has a CustomAuthorizationProvider where you can declare your own Custom OAuth Authorization and do any kind of authentication you want as below

        public class CustomAuthorizationServerProvider : OAuthAuthorizationServerProvider

    and override the "`public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)`"

4) Then you can just spin up WebAPI controllers
    [Authorize]
    public class XXXController : ApiController
    {
}

Hope this helps . Let me know if something is not clear.

【讨论】:

    【解决方案2】:

    如果您想在您的服务中使用 REST Api,您应该在服务项目中添加 WebApi,而不是在其他项目中。所以,在这种情况下,我认为你不能使用 Asp.Net Core。

    使用 Owin 在服务内启动 Rest Api 并在另一个线程中运行服务。

    // declare baseUrl in confing file by ex
    // Startup is your Startup class
    using (WebApp.Start<Startup>(baseUrl))
    {
         System.Console.WriteLine($"Listening on {baseUrl}");
         Thread.Sleep(Timeout.Infinite);
    }
    

    Imo,你应该有另一个服务来运行这个 API,这样你就可以使用 Asp.Net.Core。

    Windows Service 做一些逻辑,WebApi 使用同一个 Business Api 干扰同一个 Db。

    【讨论】:

    • 我最终使用了 2 个服务。无论如何,“一项服务”方法仍然是可取的。 Owin 是一种选择,但我更喜欢“标准”方式并使用“内置”解决方案。也许有一天这是可能的。在那之前我接受这个答案。
    猜你喜欢
    • 1970-01-01
    • 2011-05-22
    • 2011-04-04
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    相关资源
    最近更新 更多