0

I'm working on an installer that copies files into Program Files and then runs a service (via one of the files that was copied over). On the first installation this will work with no problems, but issues start to occur when the installer is run and the service is already running on the machine. This is because the installer is attempting to replace the files that already exist in Program Files, but one of those files is in use by the Windows service, so it cannot be replaced unless the service is stopped.

So I decided to use the ServiceController API to stop the service when installation begins, install the files (overwriting the existing files), and start to service again. There is very little to the code, but here it is:

Instantiate ServiceController:

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

Stopping the service:

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

Then wait for the service to be stopped and install the files:

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

And lastly restart the service:

service.Start();

With this code, the service.WaitForStatus() method will just wait forever (or longer than I'm prepared to wait at least- up to an hour). The strange thing is that I can run this code, write service.Status() to a log, check the service manually to see that it has stopped, check the log and see that ServiceController thinks the service is still running.

At first I thought that the issue was with service.Stop() so I tried creating a couple of Process objects that got the service PID and then killed the task, which stops the service instantly, but still ServiceController will not recognise that the service has stopped. If I remove the service.WaitForStatus() method from my code, an exception will be thrown since the installer is trying to overwrite a file that is in use by the service.

Also, I've tried this with different services, but the result is always the same, leading me to believe that the issue is not with the service itself.

Why is ServiceController not recognising that the service has stopped? Is there a solution or workaround to this problem? I'm working with .NET 2.0, so anything that requires higher is, unfortunately, not an option for me. Cheers.

sangram parmar
  • 8,462
  • 2
  • 23
  • 47
Oliver Nicholls
  • 1,342
  • 12
  • 24

1 Answers1

0

This answer may not be appropriate to your question but can give an idea. I also faced couple of issue while stopping services using "ServiceController" and also as pointed out in this article Read EricJ reply, I implemented like below

 service.Stop();

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

ServiceController waits for 5 minutes to stop service, if not throws TimeOutException where I'm calling TaskKill command to kill process. Below is code

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
                }
            }
Community
  • 1
  • 1