使用安装程序和部署以及安装程序类卸载用 c# 编写的应用程序

Posted

技术标签:

【中文标题】使用安装程序和部署以及安装程序类卸载用 c# 编写的应用程序【英文标题】:Uninstalling application written in c# using setup and deployment and Installer class 【发布时间】:2012-01-02 19:06:45 【问题描述】:

我的程序安装我的自定义服务并注册它。现在我要做的是取消注册服务并在卸载后删除所有文件。我正在使用 Visual Studio 和 Setup and Deployment 以及 Installer 类,我已经覆盖了我在下面介绍的一些方法:

protected override void OnAfterUninstall(IDictionary savedState)

    base.OnAfterUninstall(savedState);
    string directory = "C:\\Program Files (x86)\\MyService\\";
    if (System.IO.Directory.Exists(directory))
    
        string[] files = System.IO.Directory.GetFiles(directory);
        foreach (string file in files)
        
            System.IO.File.Delete(file);
        
        System.IO.Directory.Delete(directory);
    


protected override void OnBeforeUninstall(IDictionary savedState)

    base.OnBeforeUninstall(savedState);
    string path = "-u \"C:\\Program Files (x86)\\MyService\\AA_service.exe\"";
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.CreateNoWindow = false;
    startInfo.UseShellExecute = false;
    startInfo.FileName = "C:\\Program Files (x86)\\MyService\\InstallUtil.exe";
    startInfo.WindowStyle = ProcessWindowStyle.Hidden;
    startInfo.Arguments = path;


    Process.Start(startInfo);


它不会取消注册服务,也不会删除应用程序文件夹。谁能建议我我做错了什么?

//编辑

现在它正在尝试删除文件,但我在卸载时收到拒绝访问错误。我要删除的文件是 .exe、.dll 和其他一些文件

【问题讨论】:

如果它不起作用,它会做什么呢?任何错误,您的代码是否运行? 您不应该分发InstallUtil,因为您的代码似乎表明您正在这样做,并且您在创建基于 MSI 的安装程序时不需要手动删除文件。 @Damien_The_Unbeliever:好的,但是这个工具(InstallUtil)可以在不同的计算机上的不同位置,然后呢?我手动删除了文件,因为它们在卸载过程中不会删除,我是不是忘记了什么? @Gabriel - 不是调用 InstallUtil,而是将服务 exe 添加到 InstallUninstall 自定义操作中,并确保 InstallerClass 属性设置为 true - 你不要'根本不调用外部exe。对于已删除的文件,建议将更具体地针对这些文件的实际性质 - 您没有告诉我们任何有关这些文件是什么、如何/为什么创建它们的信息,您可能对为什么安装程序尚未删除它们... Exe 和 Dll 文件通常由安装程序安装,并在卸载时自动卸载 - 您不需要自己执行任何删除操作 - 除非您已将这些文件标记为 Permanent in文件系统编辑器属性。 【参考方案1】:

您是否将自定义操作添加到 MSI 中?如果您的卸载事件没有自定义操作触发,那么我不确定是否会调用这些事件。您是否有任何理由使用安装前后的事件而不是覆盖“卸载”命令?

如果您不调用组件的安装函数,那么安装程序也不会调用卸载函数。如果您想查看代码是否正在执行,您可以将消息框编程到卸载(或System.Diagnostics.Debugger.Attach())中。

另外,出于可移植性的考虑,我强烈建议您使用Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles) 命令来查找程序文件目录。这将移植到 x64 和 x86 以及将来对程序文件目录的任何未来修订。

其次,我也会使用Path.Combine 函数将文件夹安全地合并在一起。

编辑: 我认为您可能误用了安装过程。安装程序的自定义操作是在 MSI 安装服务后“注册”服务。它也是在被 MSI 删除之前取消注册服务。

获取 WIX 的副本或使用 Visual Studio 中的 MSI 构建器。将您的服务的项目输出放入项目中,设置自定义操作以调用您的服务 exe,然后 MSI 将为您处理安装/卸载。将调用自定义操作并向缓存注册/取消注册您的服务。

但要非常小心,如果您需要升级,服务安装程序的行为存在错误,如果您不正确连接 MSI 以处理可能发生的所有序列,它就无法成功升级或降级。

【讨论】:

你在哪里,安装程序正在自动注册服务:) 哦,还有第二个已知错误,如果任何应用程序加载具有匹配签名的 DLL,MSI 将失败,即使您有两个单独的副本(例如,一个在您的应用程序目录中,一个在其他地方)同时运行。因此它将强制重启。 @Spence 我在 OnAfterUninstall 方法中添加了this code,但它说文件正在被另一个进程使用或访问被拒绝【参考方案2】:
using system.Threading;

static void Main()

    string[] arguments = Environment.GetCommandLineArgs();
    foreach (string argument in arguments)
    
        if (argument.Split('=')[0].ToLower() == "/u")
        
            ThreadStart starter = delegate  WorkThreadFunction(argument.Split('=')[1]); ;
            new Thread(starter).Start();
            Thread.Sleep(30000);
            Application.Exit();
            return;
        
    

【讨论】:

以上是关于使用安装程序和部署以及安装程序类卸载用 c# 编写的应用程序的主要内容,如果未能解决你的问题,请参考以下文章

VS2010 安装项目在程序卸载时运行 .exe 或 C# 代码

用C#如何安装部署一个可以通过双击图片或者右键点击图片弹出菜单打开的图像浏览器程序

Azure 通知中心:安装 ID 以及如何处理应用程序的卸载

Ubuntu20.04安装配置使用卸载QT5.9.9以及第一个编写QT程序

Ubuntu20.04安装配置使用卸载QT5.9.9以及第一个编写QT程序

我用C#编写的一个Windows窗体程序怎么样打包成一个安装包?