如何让MSI安装程序在卸载服务时运行指定代码?
解决C#服务卸载时执行指定代码的问题
我碰到过类似的情况,用InstallShield MSI部署.NET服务时,直接依赖ServiceProcessInstaller的事件经常会踩坑——因为InstallShield的卸载流程不一定会默认触发.NET安装程序类的这些事件。下面给你几个靠谱的解决思路:
1. 确保.NET安装程序类被InstallShield正确调用
很多时候问题出在InstallShield的配置上,它没有把你的安装程序类纳入卸载流程。你需要这么做:
- 在InstallShield项目的Custom Actions面板里,找到卸载阶段的序列(比如
After RemoveFiles或者Before RemoveServices,根据你的需求选时机) - 添加一个新的自定义操作,类型选**.NET Installer Class**,然后指向你的服务程序集,指定要调用的方法(比如
BeforeUninstall或者你重写的Uninstall) - 一定要设置自定义操作的Execution Context为
Installer User或者System,确保有足够权限执行代码
2. 重写Installer类的Uninstall方法替代BeforeUninstall
有时候BeforeUninstall事件的触发时机在InstallShield的流程里被跳过了,换个思路,直接重写Uninstall方法:
public override void Uninstall(IDictionary savedState) { // 在这里执行你需要的卸载前逻辑,比如清理文件、记录日志等 ExecuteMyCustomUninstallCode(); // 别忘了调用基类的卸载方法,完成服务的卸载 base.Uninstall(savedState); }
这样只要InstallShield调用了你的安装程序类的Uninstall方法,这段代码就会执行。同样,要确保InstallShield里配置了调用这个安装程序类。
3. 用独立的程序作为InstallShield自定义操作
如果上面的方法还是不行,最稳妥的方式是把你的卸载逻辑写成一个独立的控制台应用(比如UncleanupTool.exe),然后在InstallShield里添加一个自定义操作:
- 在卸载序列中合适的位置(比如停止服务之后)添加一个Launch EXE类型的自定义操作
- 指向你的
UncleanupTool.exe,设置执行条件为REMOVE="ALL"(确保只有完全卸载时才执行) - 同样要注意权限,设置为以系统权限运行
关键注意事项
- 确保服务在执行你的代码前已经停止:可以在InstallShield里先添加停止服务的操作,再执行你的自定义逻辑,避免文件被占用或者服务状态异常
- 日志排查:在你的代码里添加详细的日志(比如写入事件日志或者本地文件),这样可以确认代码到底有没有被执行,方便排查问题
内容的提问来源于stack exchange,提问作者Sagar Kapadia
相关产品推荐
相关产品推荐

