繁体   English   中英

删除带有文件的 Windows 服务文件夹会引发错误

[英]Delete windows service folder with files throws error

我知道已经有人问过这个问题,但到目前为止我找不到解决方案。

我想要做的是卸载 Windows 服务并使用 C# 删除带有 Windows 服务的文件夹。

Windows 服务卸载

    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();
    }

文件夹和文件删除

    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);
        }
    }

我得到的错误

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)

这个错误是随机发生的。 .exe 文件不是只读的,有时文件会被删除。

有谁知道出了什么问题?

停止 Windows 服务并不等同于退出进程。 一个可执行文件可以容纳多个 Windows 服务(它本质上是服务的物理外壳)。

因此,您遇到的情况似乎是该服务可能停止正常,并且卸载可以继续并且文件的删除可以继续,但只能直到到达可执行文件的点为止,而尚未执行有机会退出。

停止、退出、卸载都是异步的,需要时间完成才能进入下一步。

你要做的就是遵循这个公式

  1. 如果可以,请确保您的代码以提升的权限运行; 如果你不能,你可能会遇到Access Denied 您还可以尝试更改目标可执行文件的所有权。
  2. 停止或确保服务已停止。 如果有多个服务,请停止所有服务。
  3. 等待停止实际发生。 这并不总是立竿见影的。
  4. 调用Uninstall()
  5. 等待一段时间。 检查进程是否正在运行。 如果是,您将调用Process.Kill() (请参阅下面的实现)。
  6. 最后,您可以调用DeleteFolder() ,您的实现对我来说足够了。

退出进程

编写一个看起来像这样的方法。 你可能想要调整它。

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);
    }
}

毕竟,你应该很高兴去。

服务是否停止/可执行文件停止,程序是否具有管理员访问权限? 如果您没有管理员访问权限,请参阅: 如何强制我的 .NET 应用程序以管理员身份运行? 以管理员身份运行。 卸载程序时,几乎总是需要管理员权限。 如果仍然失败,则您不是该文件的所有者,您必须将所有者更改为您自己或管理员。 您可以在此处以编程方式执行此操作: 在 C# 中获取/设置文件所有者

我认为你必须先停止服务。 尝试使用

sc stop <service name>

停止服务。 然后卸载应该可以工作。 如果您的卸载代码不起作用,请尝试使用 installutil.exe。 它也可以提供您的错误输出。 如果 exe 当前正在执行,则无法删除它,因此当您尝试删除它时,请确保 exe 未在执行。

您可以使用安装项目,它会自动生成卸载程序并为您提供一系列可能性。

服务安装程序示例

您必须在市场上下载插件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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