Dotnet 5.0 服务作为 EXE 运行,但在启动服务时出现 1053 超时:服务未及时响应启动或控制请求

Dotnet 5.0 Service Runs as EXE but when starting service times out with 1053: Service did not respond in time to start or control request

我有 Linux 运行ning 服务的背景,第一次在 Microsoft 环境中工作。我敢肯定,代码在很多方面都可以改进,第一步是获得 运行ning 服务。我参考了许多 posts 和文档,但我还不能完全理解 Microsoft 服务和 dotnet 与使用 apache 运行ning django 的 linux 环境相比如何交互例如应用程序。

我正在使用 Visual Basic Mac 作为开发,dotnet 5.0 C# 环境来构建一个服务,该服务侦听用于创建新文件的目录,然后 运行s 一个包含文件信息的脚本.我使用 dotnet 5.0 环境部署到 Windows 10 x-64。我可以在目标机器上编译一个 .exe 和 运行,它工作正常。然后我使用 sc.exe 构建服务,无论我是从 Services Manager GUI 还是从 Powershell 运行,服务总是会超时。我正在尝试弄清楚如何让服务继续 运行ning。该服务将写入我的日志文件,如果将新文件添加到目标目录,它甚至会处理该文件,但随后它总是会超时并出现以下错误:

Error 1053: the service did not respond to the start or control request in a timely fashion

我的步骤和代码如下:

使用 Visual Studio 为 Mac 创建 Worker 服务。

我的 Program.cs 是从一个模板构建的,并添加了一些现在为空的其他方法,但我认为会很有用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace MyService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((hostingContext, config) =>
                {
                    //config.AddJsonFile("custom_settings.json");
                })
                .ConfigureLogging(logging =>
                {
                    //builder.AddFile("logs/app-{Date}.json"), isJson: true);
                })
                .ConfigureServices((hostContext, services) =>
                {
                    services.AddHostedService<Worker>();
                });
    }
}

接下来是Worker.cs:

using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using HttpClientSample;

namespace MyService
{

    public class Worker : BackgroundService
    {

        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        public override async Task StartAsync(CancellationToken cancellationToken)
        {
            string path = @"C:\log.txt";
            string startText = "Start" + Environment.NewLine;
            File.AppendAllText(path, startText);
            await ExecuteAsync(cancellationToken);
        }

        public override async Task StopAsync(CancellationToken cancellationToken)
        {
            string path = @"C:\log.txt";
            string stopText = "Stop" + Environment.NewLine;
            File.AppendAllText(path, stopText);
            await base.StopAsync(cancellationToken);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {

            string path = @"C:\log.txt";
            string writeText = "Execute Async" + Environment.NewLine;
            File.AppendAllText(path, writeText);
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\files\";
            watcher.NotifyFilter = NotifyFilters.FileName;
            watcher.Created += OnCreated;
            watcher.Filter = "*.*";
            watcher.EnableRaisingEvents = true;
            File.AppendAllText(path, "watcher engaged.");

            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("worker running at: {time}", DateTimeOffset.Now);
                try
                {
                    await Task.Delay(1000, stoppingToken);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
            }
            
        }

        private static void OnCreated(object sender, FileSystemEventArgs e)
        {
            string path = @"C:\log.txt";
            string writeText = $"e: {e}";
            File.AppendAllText(path, writeText);
            MyProgram myProgram = new MyProgram(e.FullPath);
        }
    }
}

然后我在 MyProgram 中处理,一切正常。

对于服务,我首先使用以下命令编译以更正运行时间:dotnet publish -c Release -r win10-x64。然后我 FTP 将发布文件夹移至 Windows 10 机器,运行 .exe 作为管理员配置文件,它工作正常,然后通过以下文件从文件创建服务:sc.exe create myService binPath= "C:\path\to\executable.exe"。然后,我从服务管理器或使用 sc.exe start myService 从 Powershell 继续 运行 此服务。大约 60 秒后,我收到 1053 错误。

我不明白保持服务 运行ning 需要什么。我在下面尝试过的步骤:

  1. 我确保在构建服务时指向 exe。
  2. 我已经按照几个站点的建议通过注册表增加了超时:here
  3. 我已在 事件查看器 中检查 dotnet 或服务管理器问题,但未能找到问题的原因。
  4. 我已经尝试使用本地系统帐户和管理员帐户访问 运行 服务,但仍然超时。
  5. 我看到 InstallUtil 作为 sc.exe 的建议替代方案,但我还没有尝试过。我不确定该工具有多大不同?
  6. 尝试通过服务管理器 运行 时,使用 WindowsService 与 BackgroundService 会有所不同吗?
  7. 程序是否需要执行某些信号或 return 值,以便让服务知道继续 运行ning? StartTask 和 ExecuteTask 方法已经实现了 Task.delay() 和 return 值。

任何有关故障排除、解决问题或改进我的 post 的建议都将不胜感激。谢谢!

服务进程必须调用正确的 dll 函数来指示它正在启动,并接收暂停/停止事件。

在 .net 中,System.ServiceProcess.ServiceBase

中内置了这些 dll 调用的实现

asp.net 中内置了一项服务的实现,我相信它早于通用主机的引入。只需调用 IWebHost.RunAsService() 就足以将 windows 服务启动/停止事件粘合到 Web 主机启动/停止生命周期中。

我相信您需要做的就是在配置主机生成器时调用 .UseWindowsService()。这应该适用于控制台程序或网络主机。