【问题标题】:ServiceController API will not recognise that a service has stoppedServiceController API 无法识别服务已停止
【发布时间】:2015-07-01 08:20:07
【问题描述】:

我正在开发一个安装程序,它将文件复制到 Program Files 中,然后运行一项服务(通过其中一个被复制的文件)。在第一次安装时,这将没有问题,但是当安装程序运行并且服务已经在机器上运行时,问题开始出现。这是因为安装程序正在尝试替换 Program Files 中已存在的文件,但其中一个文件正在被 Windows 服务使用,因此除非服务停止,否则无法替换它。

所以我决定在安装开始时使用 ServiceController API 停止服务,安装文件(覆盖现有文件),然后重新开始服务。代码很少,但这里是:

实例化服务控制器:

try
{
    service = new ServiceController(serviceName);
}
catch (InvalidOperationException ioe)
{
    // ...
}

停止服务:

if (service.Status != ServiceControllerStatus.Stopped)
{
    service.Stop();
}

然后等待服务停止并安装文件:

service.WaitForStatus(ServiceControllerStatus.Stopped);
// install files...

最后重启服务:

service.Start();

使用此代码,service.WaitForStatus() 方法将永远等待(或者比我准备等待的时间更长,至少 - 最多一个小时)。奇怪的是我可以运行这段代码,将service.Status()写入日志,手动检查服务是否已停止,查看日志发现ServiceController认为服务仍在运行。

起初我认为问题出在service.Stop(),所以我尝试创建几个Process 对象来获取服务PID,然后终止任务,这会立即停止服务,但ServiceController 仍然不会确认服务已停止。如果我从代码中删除 service.WaitForStatus() 方法,则会引发异常,因为安装程序正在尝试覆盖服务正在使用的文件。

另外,我用不同的服务尝试过这个,但结果总是一样的,这让我相信问题不在于服务本身。

为什么ServiceController 无法识别服务已停止?这个问题有解决方案或解决方法吗?我正在使用 .NET 2.0,所以不幸的是,任何要求更高的东西都不适合我。干杯。

【问题讨论】:

    标签: c# windows-services servicecontroller


    【解决方案1】:

    此答案可能不适合您的问题,但可以提供一个想法。我在使用“ServiceController”停止服务时也遇到了一些问题,正如本文Read EricJ reply 中指出的那样,我实现如下

     service.Stop();
    
     service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMinutes(5));
    

    ServiceController 等待 5 分钟停止服务,如果没有抛出 TimeOutException,我正在调用 TaskKill 命令来终止进程。下面是代码

    using (Process process = new Process())
                {
                    try
                    {
                        string arguments = "/F /T /IM {0}";
                        process.StartInfo.FileName = "taskkill";
                        process.StartInfo.Arguments = string.Format(arguments, processName); ;
                        process.StartInfo.UseShellExecute = false;
                        process.StartInfo.RedirectStandardOutput = true;
                        process.StartInfo.RedirectStandardError = true;
    
                        StringBuilder output = new StringBuilder();
                        StringBuilder error = new StringBuilder();
    
                        using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
                        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
                        {
                            process.OutputDataReceived += (sender, e) =>
                            {
                                if (e.Data == null)
                                {
                                    outputWaitHandle.Set();
                                }
                                else
                                {
                                    output.AppendLine(e.Data);
                                }
                            };
                            process.ErrorDataReceived += (sender, e) =>
                            {
                                if (e.Data == null)
                                {
                                    errorWaitHandle.Set();
                                }
                                else
                                {
                                    error.AppendLine(e.Data);
                                }
                            };
    
                            process.Start();
                            process.BeginOutputReadLine();
                            process.BeginErrorReadLine();
    
                            if (process.WaitForExit(timeout) &&
                                outputWaitHandle.WaitOne(timeout) &&
                                errorWaitHandle.WaitOne(timeout))
                            {
                                if (process.ExitCode == 0)
                                    // Success Message
                            }
                            else
                            {
                                // Fail Message
                            }
                        }
                        if (!string.IsNullOrEmpty(output.ToString()))
                           //Out put
    
                        if (!string.IsNullOrEmpty(error.ToString()))
                            //Error out put
                    }
                    catch (Exception ex)
                    {
                        Comments = ex.Message;
                        //Exception logging
                    }
                }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      相关资源
      最近更新 更多