C# ServiceController API将无法识别服务已停止
我正在开发一个安装程序,它将文件复制到程序文件中,然后运行一个服务(通过复制的文件之一)。在第一次安装时,这将不会出现问题,但当安装程序运行且服务已在计算机上运行时,问题就会开始出现。这是因为安装程序正在尝试替换程序文件中已存在的文件,但其中一个文件正由Windows服务使用,因此除非服务停止,否则无法替换该文件 因此,我决定使用ServiceController API在安装开始时停止服务,安装文件(覆盖现有文件),然后再次开始服务。代码的内容很少,但这里是: 实例化ServiceController:C# ServiceController API将无法识别服务已停止,c#,windows-services,servicecontroller,C#,Windows Services,Servicecontroller,我正在开发一个安装程序,它将文件复制到程序文件中,然后运行一个服务(通过复制的文件之一)。在第一次安装时,这将不会出现问题,但当安装程序运行且服务已在计算机上运行时,问题就会开始出现。这是因为安装程序正在尝试替换程序文件中已存在的文件,但其中一个文件正由Windows服务使用,因此除非服务停止,否则无法替换该文件 因此,我决定使用ServiceController API在安装开始时停止服务,安装文件(覆盖现有文件),然后再次开始服务。代码的内容很少,但这里是: 实例化ServiceContro
try
{
service = new ServiceController(serviceName);
}
catch (InvalidOperationException ioe)
{
// ...
}
正在停止服务:
if (service.Status != ServiceControllerStatus.Stopped)
{
service.Stop();
}
service.Start();
然后等待服务停止并安装文件:
service.WaitForStatus(ServiceControllerStatus.Stopped);
// install files...
最后,重新启动服务:
if (service.Status != ServiceControllerStatus.Stopped)
{
service.Stop();
}
service.Start();
有了这段代码,service.WaitForStatus()
方法将永远等待(或者比我准备等待的时间长至少一个小时)。奇怪的是,我可以运行此代码,将service.Status()
写入日志,手动检查服务是否已停止,检查日志并查看ServiceController是否认为服务仍在运行
起初,我认为问题出在service.Stop()
上,因此我尝试创建了两个Process
对象,这些对象获得了服务PID,然后终止了任务,这会立即停止服务,但ServiceController
仍然无法识别服务已停止。如果我从代码中删除service.WaitForStatus()
方法,将引发异常,因为安装程序正试图覆盖服务正在使用的文件
另外,我也尝试过不同的服务,但结果总是一样的,这让我相信问题不在于服务本身
为什么
ServiceController
无法识别服务已停止?有没有解决这个问题的办法?我使用的是.NET2.0,因此,不幸的是,任何要求更高的东西都不是我的选择。干杯。这个答案可能不适合你的问题,但可以给出一个想法。在使用“ServiceController”停止服务时,我还遇到了两个问题,正如本文所指出的,我实现了如下
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
}
}