0

I'm trying to delete a directory used by a service. Because the directory is used by the service. That is why I have to stop the service. I can start or stop the service by the following code.

   static void ToggleHostService(HostStatus serviceStatus)
    {
        var hostServiceName = "ServiceHost";

        if (serviceStatus == HostStatus.run)
        {
            using (var controller = new ServiceController(hostServiceName))
            {
                if (controller.Status != ServiceControllerStatus.Running)
                    controller.Start();
                    controller.Refresh();
            }
        }
        else if (serviceStatus == HostStatus.stop)
        {
            using (var controller = new ServiceController(hostServiceName))
            {
                if (controller.Status != ServiceControllerStatus.Stopped)
                    controller.Stop();
                    controller.Refresh();
            }
        }
    }

But when I'm trying to delete the directory, I get exception as

Unhandled Exception: System.IO.IOException: The process cannot access the file ' backup.wal' because it is being used by another process.

I can see in Service manager window that the service is really stopped. But why it still complains it can't access. To make sure I run the app/code in Admin mode. I tried Please tell me how can I really force delete that directory.

masiboo
  • 4,537
  • 9
  • 75
  • 136

2 Answers2

0

I assume that you have a separate application or service to delete the directory. If you are using the directory before for some reason, then there is possibility of locking the folder by that application or service. In order to free anything related to the directory by using the below code. This needs to be written just before the delete directory:

GC.Collect();
GC.WaitForPendingFinalizers();

Also check If(Directory.Exists()) before deleting the directory to handle relevant exceptions. You can use dispose() also to free up the memory used by the directory.

-1
controller.Stop();

does not wait until the service is stopped, it just places the service in the "StopPending" state.

You have to wait until the service is stopped. I just looked into some code I wrote which does this and runs in production for some years and changed your code:

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

       // we do not need Refresh
       // controller.Refresh();

      controller.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30));
   }

For me, this is the most obvious reason for your "file in use" problem.

But, also look at Lalithanand Barla's suggestion for checking if something still uses something in this dir.

There is an additional possible problem:

Normally, a Windows service starts one or more worker threads / tasks. In OnStop() method, a service should wait until all threads are stopped.

If the service you are trying to stop does not behave this way, there could be threads still alive which also cause file in use.

I don't really have a good solution for that, perhaps retrying your delete operation with some sleep (a second or so) between.

There could also be the possibilty that the service does not only has pending threads, but it also starts another process during OnStart. Then it will be even more difficult.

Rainer Schaack
  • 1,558
  • 13
  • 16
  • I tried it and still getting the same error. Even I tried with 120 seconds. – masiboo Jan 28 '18 at 15:19
  • Ok, I see. I overlooked your notice "I can see in Service manager window that the service is really stopped". Nevertheless, you should call WaitForStatus(). Is it the same file every time (backup.wal) ? Seems a PostGreSQL file. write-ahead-log.. ? As others noted, you should really check for open file handles... – Rainer Schaack Jan 28 '18 at 19:31
  • How to check any busy files or directories programmatically? – masiboo Jan 28 '18 at 20:39