使用从属服务重新启动服务?

joh*_*nny 10 .net c# windows-services

具有启动CSHARP,例如和SO问题(适当注意到有关重新启动从C#中的窗口服务,并无法重新启动服务),并与各种其他问题重启只是一个服务,我想知道,最好的方法是什么,重新启动服务与相关的服务(例如Message Queuing,在其上Message Queuing Triggers取决于,或者IIS,在其上FTP PublishingWorld Wide Web Publishing依赖).mmc管理单元自动执行此操作,但代码似乎没有提供相同的功能(至少不那么容易).

Stop的MSDN文档说"如果任何服务依赖于此服务进行操作,它们将在此服务停止之前停止.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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果该服务依赖关系嵌套(递归)或周期性的(如果这甚至有可能...) -如果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
Run Code Online (Sandbox Code Playgroud)

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

此外,依赖但但当前停止的服务将列在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)(或者只是重新启动"所有"依赖服务 -它将跳过已经开始的那些),但这只是暂时推迟主服务的启动,直到其中一个依赖关系抱怨它,所以这并没有真正帮助.

现在寻找就像重新启动所有依赖项是最简单的方法,但是忽略(现在)管理已经停止的服务等等......

joh*_*nny 4

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

同样, ,StartService()StopService()方法RestartService()遵循示例中概述的约定,以及问题本身中已经引用的约定(即它们包装启动/停止行为以避免“已启动/停止”类型的异常),并补充说,如果Service传入a (如下例所示),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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)