简体   繁体   中英

Delete windows service folder with files throws error

I know this question was already asked, but I couldn't find the solution so far.

What I'm trying to do is uninstall a windows service and delete the folder with the windows service using C#.

Windows service uninstall

    public static void Uninstall(string exeFilename)
    {
        var commandLineOptions = new string[1] { "/LogFile=uninstall.log" };

        if (!Directory.Exists(exeFilename)) return;

        var fileNames = Directory.GetFiles(exeFilename);
        var serviceFile = fileNames.FirstOrDefault(f => f.EndsWith(".exe"));
        var serviceFileName = Path.GetFileName(serviceFile);
        var serviceName = Path.GetFileNameWithoutExtension(serviceFile);

        var serviceExists = ServiceController.GetServices().Any(s => s.ServiceName == serviceName);

        if (!serviceExists) return;

        var installer =
            new AssemblyInstaller($"{exeFilename}\\{serviceFileName}", commandLineOptions)
            {
                UseNewContext = true
            };

        installer.Uninstall(null);
        installer.Dispose();
    }

Folder and files delete

    public static void DeleteFolder(string folderPath)
    {
        if(!Directory.Exists(folderPath)) return;
        
        try
        {
            foreach (var folder in Directory.GetDirectories(folderPath))
            {
                DeleteFolder(folder);
            }

            foreach (var file in Directory.GetFiles(folderPath))
            {
                var pPath = Path.Combine(folderPath, file);
                File.SetAttributes(pPath, FileAttributes.Normal);
                File.Delete(file);
            }

            Directory.Delete(folderPath);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
    }

Error that I get

Access to the path 'c:\\services\\x\\x.exe' is denied.

 at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
 at System.IO.File.InternalDelete(String path, Boolean checkHost)
 at System.IO.File.Delete(String path)

This error occurs randomly. The .exe file is not readonly, sometimes the files get deleted.

Does anyone know what's wrong?

Stopping a Windows service does not equate to exiting a process. An executable can house multiple Windows services (it's essentially the physical shell for the services).

So what you're running into, it looks like, is that the service likely stopped just fine, and uninstall can proceed and the deletion of files can proceed, but only up until the point where it reaches the executable, which hasn't yet had a chance to exit.

Stopping, exiting, uninstalling are all asynchronous and need time to complete before moving to the next step.

What you have to do is follow this formula

  1. Ensure your code is running with elevated privileges if you can; if you can't you may run into Access Denied . You can also try changing the ownership of the target executable.
  2. Stop or ensure the service is stopped. If there are multiple services, stop all of them.
  3. Wait for stop to actually occur. It's not always immediate.
  4. Call the Uninstall() .
  5. Wait some amount of time. Check to see if the process is running. If it is you will call Process.Kill() (see an implementation below).
  6. Finally, you can call the DeleteFolder() for which your implementation looks adequate to me.

Exiting the Process

Write a method that looks something like this. You might want to tweak it.

void Exit(Process p)
{
    for (int i = 0; i <= 5; i++)
    {
        // doesn't block
        if (p.HasExited) return;

        // doesn't block; pass true to terminate children (if any)
        p.Kill(true);

        // wait 5 seconds then try again
        Thread.Sleep(5000);
    }
}

After all that you should be good to go.

Is the service stopped / executable stopped and does the program have Administrator access? If you don't have administrator access, refer to: How do I force my .NET application to run as administrator? to run as administrator. When uninstalling a program, administrator permissions are almost always required. If this still fails, you are not the owner of the file and you must change the owner to yourself or Administrators. You can do this programatically here: Getting / setting file owner in C#

I think you have to stop the service first. try using

sc stop <service name>

to stop the service. Then uninstall should work. try using installutil.exe if your uninstall code does not work. It can give your error output also. The exe cannot be deleted if it is currently executing so make sure exe is not executing when you try to delete it.

You can use setup project, it generates the uninstaller automatically and gives you a range of possibilities with it.

Example of the service installer

You must download the addon in the market place

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM