以 csharp-example 开头并适当注意相关的 SO 问题( Restart a windows services from C# 和 Cannot restart a Service )以及与仅重新启动一项服务有关的各种其他问题,我想知道重新启动服务的最佳方法是什么 具有依赖服务 (例如 Message Queuing
, Message Queuing Triggers
所依赖,或 IIS
,FTP Publishing
和 World Wide Web Publishing
所依赖)。 mmc 管理单元自动执行此操作,但代码似乎没有提供相同的功能(至少不那么容易)。
MSDN documentation for Stop说“如果任何服务的操作依赖于该服务,它们将在该服务停止之前停止。 DependentServices 属性包含依赖于该服务的一组服务,”和 DependentServices
返回一组服务。假设 StartService()
和 StopService()
遵循示例中概述的约定以及上面引用的约定(除了它们直接接受 ServiceControllers
和 TimeSpans
),我开始于:
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 B1
和 Service B2
和 Service 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 C1
和 Service 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/