I created an application to update a Windows service application (that I've also created). This "updater" application works like a charm, but only if the Windows service is already stopped.
The order of operations for the updater application is the following:
ServiceController
objectmyService.Stop()
(If it's not already in the ServiceControllerStatus.Stopped
state)myService.WaitForStatus()
myService.Close()
myService.Start()
myService.Close()
If the service is already stopped, then this does work. However, if the service was previously running, the updater application will stop the service and move on to step #5. At this point, I will get an error message saying that I cannot override the .dll files because the files are being used by another process.
At first I thought that it was my own updater application that was keeping a reference to the service through the ServiceController
object and that's when I added step #4, this did not change anything.
If I run the updater application twice, the first time it stops it and fails at the updating the .dll files. Then the second time it notices that it's already stopped and tries to update the .dll files, then it all works. The service .dll get updated and the service is started.
private static bool ServiceCommand(string serviceName, bool startService, TimeSpan timeout)
{
if (!GetServiceObject(serviceName, out ServiceController service)) return false;
try
{
// First, check to make sure it's not already started or stopped
if (service.Status == (startService ? ServiceControllerStatus.Running : ServiceControllerStatus.Stopped))
{
return true;
}
ServiceControllerStatus myTargetStatus;
if (startService)
{
service.Start();
myTargetStatus = ServiceControllerStatus.Running;
}
else
{
service.Stop();
myTargetStatus = ServiceControllerStatus.Stopped;
}
// Wait for the target status
service.WaitForStatus(myTargetStatus, timeout);
}
catch (Exception e)
{
Logger.Log("Unable to " + (startService ? "start" : "stop") + " service '" + service.ServiceName + "': " + e.Message);
return false;
}
finally
{
if (service != null) service.Close();
}
return true;
}
I believe this is where the problem lies. In step #5 all I'm doing is a File.Copy()
with the override parameter set as true. This is where I'm getting the error message The process cannot access the file '' because it is being used by another process.
Any help or input is greatly appreciated! Thanks!
An executable can report to the Service Control Manager that a service has stopped, but the executable can continue running for a while, for example to clean stuff up or let background threads finish doing their job. It shouldn't do that, it should request for more shutdown time in that case, but that's probably what's happening.
So either fix your service so that its executable stops immediately after reporting the service stopped status, or wait for your executable to stop before copying the files.
See also Service not fully stopped after ServiceController.Stop(), what is the maximum time windows service wait to process stop request and how to request for additional time.