等待服务完全停止/启动,然后继续

时间:2016-05-17 15:42:56

标签: c# .net windows-services

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

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;
}

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

所以问题是:在继续之前,我怎么能确定服务已经停止或完全启动?我几乎可以接受任何解决方案。

回复重复问题:

将这一点分开的是,它是我正在访问的远程系统,以便执行此工作。问题指出,重复的问题没有指定或显示远程方案。我会对它进行测试,如果成功,我会将其作为答案发布。然而,在此之前它并不重复。

2 个答案:

答案 0 :(得分:0)

两种解决方案:

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

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

答案 1 :(得分:0)

好的,重复问题的答案在很大程度上是正确的答案。该答案的代码(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);
            }
        }
    }