【问题标题】:Windows Service just stops. No messages, no alerts, errors, warning - nothingWindows 服务刚刚停止。没有消息,没有警报,错误,警告 - 没有
【发布时间】:2026-02-16 00:40:01
【问题描述】:

我有一个 Windows 服务,它会自行静默停止。以下是相关代码:

OnStart() 方法:

    protected override void OnStart(string[] args)
    {
        try
        {
            InitializeLogging();

            // we don't DO command line arguments
            if (args.Length > 0)
            {
                eventLog.WriteEntry("All command line arguments are ignored.  You must edit the app.config file manually to make changes to what watchers are run.");
                throw new ArgumentException("Command line arguments are ignored.");
            }

            ReadAppConfig();
            RecalculateStartTimes();
            InitializeWatchers();

        }
        catch (Exception e)
        {
            eventLog.WriteFormattedEntry("Error on Start: {0}", e.Message);
        }
        finally
        {
            eventLog.WriteEntry("Service start completed");
        }
    }

OnStop() 方法:

    protected override void OnStop()
    {
        eventLog.WriteEntry("Service stopped.");
    }

InitializeWatchers() 方法:

    private void InitializeWatchers()
    {
        try
        {

            var watchers = _watcherSection.Watchers.ToList<WatcherElement>();

            eventLog.WriteEntry(string.Format("Initializing {0} watchers.", watchers.Count()));

            var obsWatchers = watchers.ToObservable();
            obsWatchers.SelectMany(
                watcher =>
                    Observable.Timer(watcher.StartTime, TimeSpan.FromHours(watcher.Interval))
                              .SelectMany(
                                    Observable.FromAsync(
                                      async () => new
                                      {
                                          watcher,
                                          response = await CheckFolder(watcher.Path)
                                      })))
                              .Subscribe(
                                    onNext: x =>
                                    {
                                        eventLog.WriteFormattedEntry("\nWatcher: {0}, Time:{1}", x.watcher.Name, DateTimeOffset.Now);
                                        if (x.response.Success)
                                            eventLog.WriteFormattedEntry("| Success!\n| Value: '{0}'\n| Message: {0}", x.response.Value, x.response.Message);
                                        else
                                            eventLog.WriteFormattedEntry("| FAILURE!\n| Value: '{0}'\n| Message: {0}\n| Errors: '{0}'", x.response.Value, x.response.Message, x.response.Exceptions.First());
                                    },
                                    onError: e =>
                                        {
                                            var err = e;
                                            var sb = new StringBuilder();
                                            sb.AppendLine("The observer threw an error:")
                                              .AppendFormatLine("| Message: {0}", e.Message);

                                            while (e.InnerException != null)
                                            {
                                                sb.AppendFormatLine("| Inner: {0}", e.InnerException.Message);
                                                e = e.InnerException;
                                            }

                                            sb.AppendLine();
                                            eventLog.WriteEntry(sb.ToString());
                                            throw err;
                                        });

            eventLog.WriteEntry("about to wait.");
            obsWatchers.Wait();
            eventLog.WriteEntry("passed the wait");
        }
        catch (Exception e)
        {
            eventLog.WriteFormattedEntry("Exception thrown in InitializeWatchers(WatchersSection): {0}", e.Message);
            throw;
        }
    }

当我运行此代码时,服务正常启动。事件日志记录了三个事件:

  1. 服务和日志记录已启动。
  2. 正在初始化 1 个观察者。
  3. 服务启动完成。

...它停止了。我必须手动刷新服务窗口,但它退出运行。我没有收到任何错误或任何其他 eventLog 条目。

令人沮丧的是,这段代码可以完美地用作控制台应用程序。我已将所有 eventLog.WriteEntry() 更改为 Console.WriteLine(),但除此之外,代码相同并按预期执行。

任何智慧都会受到赞赏。

【问题讨论】:

    标签: windows-services system.reactive reactive-programming


    【解决方案1】:

    我怀疑服务控制管理器正在终止您的服务,因为它没有在超时窗口(30 秒,IIRC)内从 OnStart 返回。

    我在managed service basics 上有一篇博客文章,它基于blog entry by the BCL team。请注意,MSDN 文档不足;您必须了解 BCL 团队博客文章中的信息才能正确编写托管服务。

    【讨论】:

    • 感谢您的资源 - 我会仔细阅读并回复您。
    【解决方案2】:

    不要使用obsWatchers.Wait() 阻止并导致斯蒂芬所说的问题,而是异步订阅。

    将此属性添加到您的类中:

    private SingleAssignmentDisposable _subscription = new SingleAssignmentDisposable();
    

    将此添加到您的 OnStop 方法中:

    _subscription.Dispose();
    

    在您的InitializeWatchers() 中,消除对Subscribe 的嵌套调用,并将obsWatchers.Wait() 替换为订阅调用,如下所示:

    private void InitializeWatchers()
    {
        try
        {
    
            var watchers = _watcherSection.Watchers.ToList<WatcherElement>();
    
            eventLog.WriteEntry(string.Format("Initializing {0} watchers.", watchers.Count()));
    
            var obsWatchers = watchers.ToObservable();
            _subscription.Disposable = obsWatchers
                .SelectMany(watcher => Observable
                    .Timer(watcher.StartTime, TimeSpan.FromHours(watcher.Interval))
                    .SelectMany(_ => Observable.FromAsync(async () => new
                          {
                              watcher,
                              response = await CheckFolder(watcher.Path)
                          })))
                 .Subscribe(
                     onNext: x =>
                     {
                         eventLog.WriteFormattedEntry("\nWatcher: {0}, Time:{1}", x.watcher.Name, DateTimeOffset.Now);
                         if (x.response.Success)
                             eventLog.WriteFormattedEntry("| Success!\n| Value: '{0}'\n| Message: {0}", x.response.Value, x.response.Message);
                         else
                             eventLog.WriteFormattedEntry("| FAILURE!\n| Value: '{0}'\n| Message: {0}\n| Errors: '{0}'", x.response.Value, x.response.Message, x.response.Exceptions.First());
                     },
                     onError: e =>
                     {
                         var err = e;
                         var sb = new StringBuilder();
                         sb.AppendLine("The observer threw an error:")
                           .AppendFormatLine("| Message: {0}", e.Message);
    
                         while (e.InnerException != null)
                         {
                             sb.AppendFormatLine("| Inner: {0}", e.InnerException.Message);
                             e = e.InnerException;
                         }
    
                         sb.AppendLine();
                         eventLog.WriteEntry(sb.ToString());
                         throw err;
                     });
            eventLog.WriteEntry("passed the wait");
        }
        catch (Exception e)
        {
            eventLog.WriteFormattedEntry("Exception thrown in InitializeWatchers(WatchersSection): {0}", e.Message);
            throw;
        }
    }
    

    【讨论】: