Windows桌面应用:基于布尔值阻止卸载的C#实现咨询
阻止Windows桌面MSI应用卸载的C#实现方案
要基于布尔值控制应用卸载,核心是拦截Windows Installer的卸载流程,或监控卸载相关系统事件。需注意:Windows系统有自身权限与保护机制,无法做到100%阻止(如用户使用管理员权限、第三方卸载工具等场景),但可实现常规场景下的拦截。
方案1:MSI自定义动作(推荐,与安装包集成)
通过MSI的自定义动作,在卸载序列启动前读取布尔值配置,判断是否终止卸载。
步骤与代码示例
- 新建C#自定义动作项目,引用
Microsoft.Deployment.WindowsInstaller(可通过NuGet安装Microsoft.Deployment.WindowsInstaller包)。 - 编写拦截卸载的代码:
using Microsoft.Deployment.WindowsInstaller; public class CustomActions { [CustomAction] public static ActionResult BlockUninstall(Session session) { // 从注册表读取控制卸载的布尔值(自定义注册表路径) bool allowUninstall = true; using (var regKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\YourAppIdentifier")) { if (regKey != null) { var value = regKey.GetValue("AllowUninstall"); allowUninstall = value != null && (bool)value; } } if (!allowUninstall) { session.Log("Uninstall blocked by configuration"); // 弹出错误提示 session.Message(InstallMessage.Error, new Record(1) { FormatString = "当前应用禁止卸载,请联系管理员。" }); return ActionResult.Failure; } return ActionResult.Success; } }
- 将自定义动作集成到MSI包(以WiX为例):
在WiX的Product节点中添加配置,确保卸载前执行自定义动作:
<CustomAction Id="BlockUninstall" BinaryKey="CustomActionsDll" DllEntry="BlockUninstall" Execute="immediate" Return="check" /> <InstallExecuteSequence> <Custom Action="BlockUninstall" Before="RemoveFiles">NOT Installed</Custom> </InstallExecuteSequence>
方案2:后台监控服务(独立程序,适合已安装应用)
编写Windows服务,监控msiexec.exe的启动事件,当检测到自身应用的卸载请求时,根据布尔值终止进程。
代码示例
using System; using System.ServiceProcess; using System.Diagnostics; using System.Management; using Microsoft.Win32; namespace UninstallMonitorService { public partial class UninstallMonitor : ServiceBase { private ManagementEventWatcher _processWatcher; public UninstallMonitor() { InitializeComponent(); InitializeWatcher(); } private void InitializeWatcher() { // 监控msiexec.exe启动事件 var query = new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace WHERE ProcessName = 'msiexec.exe'"); _processWatcher = new ManagementEventWatcher(query); _processWatcher.EventArrived += OnUninstallAttempt; } protected override void OnStart(string[] args) { _processWatcher.Start(); } protected override void OnStop() { _processWatcher.Stop(); } private void OnUninstallAttempt(object sender, EventArrivedEventArgs e) { var processId = int.Parse(e.NewEvent.Properties["ProcessId"].Value.ToString()); using (var process = Process.GetProcessById(processId)) { // 替换为你的MSI产品GUID var targetProductCode = "{YOUR-APP-PRODUCT-CODE-GUID}"; if (process.StartInfo.Arguments.Contains("/x") && process.StartInfo.Arguments.Contains(targetProductCode)) { bool allowUninstall = GetUninstallPermission(); if (!allowUninstall) { try { process.Kill(); EventLog.WriteEntry("UninstallMonitor", "Uninstall blocked successfully", EventLogEntryType.Information); } catch (Exception ex) { EventLog.WriteEntry("UninstallMonitor", $"Failed to block uninstall: {ex.Message}", EventLogEntryType.Error); } } } } } private bool GetUninstallPermission() { // 从注册表读取布尔配置 using (var regKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\YourAppIdentifier")) { if (regKey == null) return true; var value = regKey.GetValue("AllowUninstall"); return value != null && (bool)value; } } } }
注意事项
- 权限要求:自定义动作与监控服务均需管理员权限才能正常执行,否则无法修改注册表或终止系统进程。
- 局限性:无法阻止用户通过安全模式、第三方卸载工具或直接删除文件的方式卸载应用。
- 合规性:阻止卸载可能违反Windows应用规范,建议仅在企业内部场景使用,并提前告知用户。
内容的提问来源于stack exchange,提问作者Elanchezhiyan P
相关产品推荐
相关产品推荐

