ServiceController API无法识别服务已停止

时间:2015-07-01 08:20:07

标签: c# windows-services servicecontroller

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

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

实例化ServiceController:

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()所以我尝试创建了几个获得服务PID的Process个对象然后杀死了任务,这会立即停止服务,但仍然{ {1}}无法识别该服务已停止。如果我从代码中删除ServiceController方法,则会抛出异常,因为安装程序正在尝试覆盖服务正在使用的文件。

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

为什么service.WaitForStatus()无法识别服务已停止?这个问题有解决方案或解决方法吗?我正在使用。NET 2.0 ,所以任何需要更高的东西都不是我的选择。欢呼声。

1 个答案:

答案 0 :(得分:0)

这个答案可能不适合您的问题,但可以提出一个想法。我在使用“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
                }
            }