我有一个从Visual Studio中的项目创建的可执行文件,我想通过该可执行文件创建服务(这样我就可以在不需要控制台窗口的情况下运行它)。我发布项目,并使用以下方法创建Windows服务:

sc create MY.SERVICE binpath= "C:\Program Files\Project\serviceProj\myService.exe


该服务将按预期显示在Windows Services Manager中。但是,每当我尝试启动该服务时,它将在大约2秒钟后失败,并给我以下错误:

Windows could not start the MY.SERVICE on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion.


我所做的事情:

从调试更改为在Visual Studio中发布

以管理员身份运行所有内容(创建服务,发布项目,启动服务等)。

我还在某处读到,增加服务管理器等待服务启动的时间可能会起作用。我添加了Windows注册表值来执行此操作,但不幸的是它没有用。

从命令提示符启动服务通常只需要2-3秒即可启动并开始侦听请求,因此我不确定发生了什么。

任何帮助表示赞赏。

这是我的Startup.cs类:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Serialization;
using Microsoft.AspNetCore.Hosting.WindowsServices;
using System.Diagnostics;
using System.IO;
using Serilog;
using System.Linq;

namespace My.Service
{
    public class Startup
    {
        public static void Main(string[] args)
        {
            var exePath = Process.GetCurrentProcess().MainModule.FileName;
            var directoryPath = Path.GetDirectoryName(exePath);

            if (Debugger.IsAttached || args.Contains("--debug"))
            {
                var host = new WebHostBuilder()
                   .CaptureStartupErrors(true)
                   .UseKestrel()
                   .UseUrls("http://localhost:5002")
                   .UseContentRoot(Directory.GetCurrentDirectory())
                   .UseIISIntegration()
                   .UseStartup<Startup>()
                   .Build();
                host.Run();
            }
            else
            {
                var host = new WebHostBuilder()
                    .UseKestrel()
                    .UseUrls("http://localhost:5002")
                    .UseContentRoot(directoryPath)
                    .UseIISIntegration()
                    .UseStartup<Startup>()
                    .Build();
                host.RunAsService();
            }
        }


        public Startup(IHostingEnvironment env)
        {
            //Setup Logger
            Log.Logger = new LoggerConfiguration()
                .WriteTo.Trace()
                .MinimumLevel.Debug()
                .CreateLogger();
            // Set up configuration sources.
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json");
            Configuration = builder.Build();
        }

        public IConfigurationRoot Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc().AddJsonOptions(options =>
            {
                options.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();
            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime lifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}");
            });
        }
    }
}

最佳答案

您看到的错误是Windows发出的通知,表明您启动的服务尚未在合理的时间内(30秒)完成启动。

之所以发生这种情况,是因为您已将应用程序的逻辑塞入了应用程序的公共Main()方法中,而这并不是Windows服务所需要的。

Windows服务包括一些支持该服务的结构。服务的Main()中通常发生的所有事情是加载服务,但实际上并未启动它的运行。该服务包括事件处理程序,以支持对标准服务操作的响应,例如启动,停止,暂停,继续以及关闭系统时的处理。

所有Windows服务都具有的这种结构有点复杂,必须按照操作系统的规范进行构建。尽管可以手动构建Windows服务,但可能很难正确设置所有管道,因此让Visual Studio在这里帮助您变得容易得多。

构建Windows服务时,最简单,最直接的方法是让VS在创建新的Visual Studio项目时创建Windows服务项目。新项目将包括您从一开始就需要的大多数必需的管道和服务功能。

当然,您可以手动构建服务,但实际上没有理由。如果您确实想沿着手动构建的路径走下去,则至少需要执行以下操作(一个警告-我正在从内存中执行此操作,而我又回到了VS 2017,所以这可能并不完全正确) ):


将Windows服务组件添加到您的项目。为此,请在解决方案资源管理器中右键单击您的项目,然后选择“添加”。在出现的菜单中,选择“组件...”。在出现的对话框中,选择“ Windows服务”。提示一下,在按下“添加”按钮之前给文件起一个有意义的名称。
添加该Windows Service组件后,右键单击它并设置其属性。
要对OnStart,OnStop,OnPause,OnContinue和OnShutdown事件处理程序进行编程,请右键单击Windows Service设计空间(或在解决方案资源管理器中右键单击该文件),然后选择“查看代码”。


关于构建Windows服务,还有许多要了解的事情,这里没有空间。我建议您在该领域做很多事情之前,先找到一些关于该主题的良好文档,并进行研究,因为此处做错了可能会对运行您的服务的计算机产生极大的影响。看看MSDN: Walkthrough: Creating a Windows Service Application in the Component Designer。它应该有助于更彻底地解释这一点。

10-07 20:00
查看更多