我有一个从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。它应该有助于更彻底地解释这一点。