【问题标题】:Wait for a service to completely Stop / Start before continuing等待服务完全停止/启动,然后再继续
【发布时间】:2016-05-17 15:42:56
【问题描述】:

好吧……很简单。实际上,我已经让这个大部分工作了。然而,有时服务实际上并没有停止,尽管程序似乎不同意。该程序只是停止一项服务,将文件从一个地方复制到另一个地方,然后启动一项服务。该服务锁定了正在复制的文件,因此它必须停止。

internal void StopTheService()
    {
        Logger.Log("Stopping the service.");
        lock (myLock) {
            var sc = new ServiceController() { ServiceName = nameOfService, MachineName = nameOfServerWithService };
            sc.Stop();
            sc.WaitForStatus(ServiceControllerStatus.Stopped);
        }
        Logger.Log("Service stopped."); 
    }

internal void StartTheService()
    {
        Logger.Log("Starting the service.");
        lock (myLock) {
            var sc = new ServiceController() { ServiceName = nameOfService, MachineName = nameOfServerWithService };
            sc.Start();
            sc.WaitForStatus(ServiceControllerStatus.Running);
        }
        Logger.Log("Service Started.");
    }

此代码在大多数情况下都有效,但问题是当它认为服务已停止并继续进行下一步复制时,它会失败。我可以等待它在 while 循环中停止/启动,例如:

while(count<5){
    sc.WaitForStatus(ServiceControllerStatus.Stopped);
    count = count+1;
}

但我认为这也可能失败。尽管我的查询可能不正确,但我在网上找到的所有内容都不能完全回答我的问题。运行此代码的应用程序是一个多线程环境(因此是锁)。如果我在失败后重新运行应用程序,它就可以工作。它返回的错误是您尝试打开另一个文件时遇到的典型“文件在另一个进程中打开”错误。请注意,这是一个远程环境,其中包含我正在访问的服务和文件,是的,我确实拥有管理员权限,因此 UAC 不是问题。

所以问题是:在继续之前,我如何确定服务已完全停止或启动?我对几乎任何解决方案都持开放态度。

针对重复的问题:

与众不同的是,它是一个远程系统,我正在访问它以执行这项工作。标注为重复问题的问题未指定或显示远程场景。但是,我将对其进行测试,如果成功,我会将其发布为答案。但是在那之前它不是重复的。

【问题讨论】:

  • "是当它认为服务已经停止并继续下一步,复制时,它失败了。" - 你调试过这个吗?我可以将其视为“服务停止,但操作系统有点忘记清理已处理的文件”——但仅此而已。这听起来确实像一个令人讨厌的错误,您可能根本无法解决(而且我从未经历过)。
  • @Richard Barker 我一直遇到这个问题,stackoverflow.com/a/1597244/60188 很好地解决了所有问题。
  • @AntonGogolev 哇,这是一个旧的。当我输入几乎完全相同的问题名称时,Stackoverflow 没有找到它。
  • @RichardBarker 啊,这是一个远程机器...这可能会很有趣。也许,一些 WMI?
  • @AntonGogolev 是的,这就是它与众不同而不是重复的原因(至少完全如此)

标签: c# .net windows-services


【解决方案1】:

两种解决方案:

A.更新服务代码以在数据库或文件的开始/结束时刷新其状态。您的程序会读取状态。

B.您的程序会检查服务线程是否存在。

【讨论】:

  • A 需要更新服务 - 我希望避免这种情况,但如果归根结底,我会的。 B 可能是可能的,但前提是我可以从远程机器上做到这一点。
【解决方案2】:

好的,重复问题的答案大部分是正确答案。该答案 (stackoverflow.com/a/1597244/60188) 上的代码大部分是正确的,除了远程机器部件。

public void StopServiceAndWaitForExit()
    {

        using (var controller = new ServiceController(nameOfService, nameOfServerWithService))
        {
            var ssp = new SERVICE_STATUS_PROCESS();
            int ignored;

            if (!QueryServiceStatusEx(controller.ServiceHandle.DangerousGetHandle(), SC_STATUS_PROCESS_INFO, ref ssp, Marshal.SizeOf(ssp), out ignored))
                throw new Exception("Couldn't obtain service process information.");

            if (ssp.dwServiceType != SERVICE_WIN32_OWN_PROCESS)
                throw new Exception("Can't wait for the service's hosting process to exit because there may be multiple services in the process (dwServiceType is not SERVICE_WIN32_OWN_PROCESS");

            if ((ssp.dwServiceFlags & SERVICE_RUNS_IN_SYSTEM_PROCESS) != 0)
                throw new Exception("Can't wait for the service's hosting process to exit because the hosting process is a critical system process that will not exit (SERVICE_RUNS_IN_SYSTEM_PROCESS flag set)");

            if (ssp.dwProcessId == 0)
                throw new Exception("Can't wait for the service's hosting process to exit because the process ID is not known.");

            using (Process process = Process.GetProcessById(ssp.dwProcessId, nameOfServerWithService))
            {
                var threadData = new ProcessWaitForExitData();

                threadData.Process = process;

                var processWaitForExitThread = new Thread(ProcessWaitForExitThreadProc);

                processWaitForExitThread.IsBackground = Thread.CurrentThread.IsBackground;
                processWaitForExitThread.Start(threadData);

                controller.Stop();

                lock (threadData.Sync)
                    while (!threadData.HasExited)
                        Monitor.Wait(threadData.Sync);
            }
        }
    }

【讨论】:

  • ProcessWaitForExitThreadProc from 1597244 answer 正在使用 Process.WaitForExit,这会引发 NotSupportedException 远程计算机不支持该功能。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-10-03
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多