c# - 重新启动具有依赖服务的服务?

标签 c# .net windows-services

csharp-example 开头并适当注意相关的 SO 问题( Restart a windows services from C#Cannot restart a Service )以及与仅重新启动一项服务有关的各种其他问题,我想知道重新启动服务的最佳方法是什么 具有依赖服务 (例如 Message QueuingMessage Queuing Triggers 所依赖,或 IISFTP PublishingWorld Wide Web Publishing 所依赖)。 mmc 管理单元自动执行此操作,但代码似乎没有提供相同的功能(至少不那么容易)。

MSDN documentation for Stop说“如果任何服务的操作依赖于该服务,它们将在该服务停止之前停止。 DependentServices 属性包含依赖于该服务的一组服务,”和 DependentServices 返回一组服务。假设 StartService()StopService()遵循示例中概述的约定以及上面引用的约定(除了它们直接接受 ServiceControllersTimeSpans),我开始于:

public static void RestartServiceWithDependents(ServiceController service, TimeSpan timeout)
{
    ServiceController[] dependentServices = service.DependentServices;

    RestartService(service, timeout); // will stop dependent services, see note below* about timeout...

    foreach (ServiceController dependentService in dependentServices)
    {
        StartService(dependentService, timeout);
    }
}

但是如果服务依赖项是嵌套的(递归的)或循环的(如果这甚至可能......) - 如果 Service A依赖于 Service B1Service B2Service C1取决于 Service B1 ,似乎在“重启”Service A通过这种方法将停止 Service C1但不会重新启动它...

为了使此示例图片更清晰,我将遵循服务 mmc 管理单元中的模型:
The following system components depend on [Service A]:
  - Service B1
    - Service C1
  - Service B2

有没有更好的方法来解决这个问题,还是只需要递归地进入并停止每个依赖服务,然后在重新启动主服务后重新启动它们?

此外,是否会在 DependentServices 下列出相关但当前停止的服务?如果是这样,这不会重新启动它们吗?如果是这样,我们是否也应该控制它?这似乎变得越来越困惑......

*注:我意识到timeout在这里没有完全正确地应用(总体超时可能比预期长很多倍),但现在这不是我关心的问题 - 如果你想修复它,很好,但不要只是说 '超时坏了……'

更新:经过一些初步测试,我发现(/确认)以下行为:
  • 停止其他服务(例如 Service A )所依赖的服务(例如 Service B1 )将停止其他服务(包括“嵌套”依赖项,例如 Service C1 )
  • DependentServices 确实包括所有状态(运行、停止等)下的依赖服务,还包括嵌套依赖,即 Service_A.DependentServices将包含 {Service B1, Service C1, Service B2} (按此顺序,因为 C1 取决于 B1 )。
  • 启动依赖于其他人的服务(例如 Service B1 依赖于 Service A)也将启动必要的服务。

  • 因此,上面的代码可以被简化(至少部分地)只停止主服务(这将停止所有依赖服务),然后重新启动最依赖的服务(例如 Service C1Service B2)(或只是重新启动“所有”依赖服务 - 它会跳过已经启动的服务),但这实际上只是暂时推迟主服务的启动,直到依赖项之一提示它,所以这并没有真正的帮助。

    现在看起来只是重新启动所有依赖项是最简单的方法,但这忽略了(目前)管理已经停止的服务等......

    最佳答案

    好了,终于实现了。我已将其作为单独的答案发布,因为我已经在我的问题的原始更新中得出了这个结论,该更新是在第一个答案之前发布的。

    再次,StartService() , StopService()RestartService()方法遵循示例中概述的约定,并且问题本身已经引用了这些约定(即它们包装了启动/停止行为以避免“已经启动/停止”类型的异常),并附上如果 Service传入(如下例),Refresh()在检查其 Status 之前调用该服务.

    public static void RestartServiceWithDependents(ServiceController service, TimeSpan timeout)
    {
        int tickCount1 = Environment.TickCount; // record when the task started
    
        // Get a list of all services that depend on this one (including nested
        //  dependencies)
        ServiceController[] dependentServices = service.DependentServices;
    
        // Restart the base service - will stop dependent services first
        RestartService(service, timeout);
    
        // Restore dependent services to their previous state - works because no
        //  Refresh() has taken place on this collection, so while the dependent
        //  services themselves may have been stopped in the meantime, their
        //  previous state is preserved in the collection.
        foreach (ServiceController dependentService in dependentServices)
        {
            // record when the previous task "ended"
            int tickCount2 = Environment.TickCount;
            // update remaining timeout
            timeout.Subtract(TimeSpan.FromMilliseconds(tickCount2 - tickCount1));
            // update task start time
            tickCount1 = tickCount2;
            switch (dependentService.Status)
            {
                case ServiceControllerStatus.Stopped:
                case ServiceControllerStatus.StopPending:
                    // This Stop/StopPending section isn't really necessary in this
                    //  case as it doesn't *do* anything, but it's included for
                    //  completeness & to make the code easier to understand...
                    break;
                case ServiceControllerStatus.Running:
                case ServiceControllerStatus.StartPending:
                    StartService(dependentService, timeout);
                    break;
                case ServiceControllerStatus.Paused:
                case ServiceControllerStatus.PausePending:
                    StartService(dependentService, timeout);
                    // I don't "wait" here for pause, but you can if you want to...
                    dependentService.Pause();
                    break;
            }
        }
    }
    

    关于c# - 重新启动具有依赖服务的服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7639392/

    相关文章:

    c# - 我应该在 Windows 服务中调用基类的方法吗?

    c# - 如何从 Web 应用程序调用 Windows 服务方法

    c# - 为引用对象指定 Entity Framework 中的列名称

    c# - 专注于具有属性 TextMode ="MultiLine"的文本框,用于输入按键

    c# - Linq2Sql、OOP、DependencyInjection问题

    c++ - 托管类中的 native 指针

    c# - Automapper,INamingConvention Camelcase 属性为带下划线的大写

    c# - 使用 HttpClient 时记录请求/响应消息

    c# - 将数据绑定(bind)到 DataGridTextColumn.Header 内的 TextBox

    windows-services - 服务看门狗设计