要求卸载前关闭 Winforms 应用程序
Posted
技术标签:
【中文标题】要求卸载前关闭 Winforms 应用程序【英文标题】:Require winforms app to shutdown before uninstall 【发布时间】:2012-05-26 14:49:35 【问题描述】:答案可能涉及自定义卸载操作,但这似乎是一个重大的过度站点,并且是每个应用程序都想要的东西,所以我想我会看看是否有一些我遗漏的简单内容。
我在 Visual Studio 2008 中使用 C#、Winform 项目创建了几个项目。一种使用单击一次安装,一种使用安装项目。它们都允许您在卸载时保持应用程序运行。在 Windows 7 上,您确实会收到警告,但可以选择让它继续运行……在 XP 上甚至没有警告。
说我疯了,但是想到我的所有程序文件都被删除了,而我的应用程序仍在运行,这听起来根本不是一个好的设计。想到 GPF 的记忆,或者 .NET 对 DLL 使用延迟加载的方式,在需要加载 DLL 时也可能是个问题,并且已经消失了。
如果您的应用仍在运行,有没有一种简单的方法来禁止卸载?
我使用的是 C#,但我使用的是 VB.NET 单实例类来确保我的应用程序只运行一次,所以也许可以利用它而不是创建一个互斥体来检查?
此外,我的应用程序只允许“每个用户”安装,而不是“所有用户”,所以我不必担心我的应用程序在另一个会话中运行(如果是,可以继续运行,因为它应该是100% 自己的副本)。
编辑:因为我没有找到其他任何东西,所以我尝试了互斥锁的想法,但它不起作用。这是我的代码:
在应用程序中,我有这个来创建命名互斥体并在应用程序运行时保持活动状态:
System.Threading.Mutex m = new System.Threading.Mutex(true, "SafeShare");
SingleInstanceApplication.Run(TabForm, NewInstanceHandler);
GC.KeepAlive(m);
在卸载操作中,我有这个循环,直到它们退出(因为提供取消选项似乎并不容易):
while (true)
bool createdNew;
System.Threading.Mutex m = new System.Threading.Mutex(true, "SafeShare", out createdNew);
m.ReleaseMutex();
if (createdNew)
break;
MessageBox.Show(null,"Close XXX and click OK to continue uninstall.","Uninstall");
createdNew 从未在卸载操作中设置,几乎就像它在不同的会话或其他东西下运行一样。我没有尝试将 Global\ 添加到互斥锁名称中,但无论如何这对我的应用程序都不起作用,因为我会按用户进行安装,因此即使卸载了一个安装,一个安装也应该能够在另一个会话上继续运行。
【问题讨论】:
不熟悉您需要哪个 API - User32.dll 或 kernel32.dll ?? - 但您会查询进程 ID,或名称等于xxx
。
功能,不是错误,任何锁定的文件都会在下次重启时被删除。如果您不想利用这一点(为什么?什么“GPF”?),那么您将需要自定义卸载操作。首先需要可靠地检测程序仍在运行。是的,命名互斥体可以做到这一点。
GPF = 一般页面错误,当 Windows 内部需要从 EXE/DLL 加载资源或某些东西并且它丢失时发生。大多数情况下发生在通过网络运行 EXE 并且您失去网络连接时,但据我所知,只要文件句柄无效或文件丢失,就会发生这种情况。
我正在尝试互斥锁的想法,我会更新我的问题,因为即使这样似乎也有问题。另外,我希望我的应用程序关闭的另一个原因是它有时会重新创建 user.config 文件,并且出于安全原因,我希望卸载后的所有内容都消失(我相信用户也会喜欢这个)。
【参考方案1】:
简短的回答是没有简单的方法可以做到这一点,因为这不是微软希望你做的事情。
我的答案确实最终使用了互斥锁,一旦我得到正确的代码,它似乎工作正常。
在我做的应用程序中:
System.Threading.Mutex m = new System.Threading.Mutex(true, "MyMutexNameHere");
SingleInstanceApplication.Run(TabForm, NewInstanceHandler);
GC.KeepAlive(m);
SingleInstanceApplication.Run 行是运行您的应用程序的内容,我使用的是 VB.NET 框架。
在我执行的自定义卸载操作中:
while (true)
bool createdNew;
System.Threading.Mutex m = new System.Threading.Mutex(true, "MyMutexNameHere", out createdNew);
m.Close();
if (createdNew)
break;
MessageBox.Show(null,"Close XXX and click OK to continue uninstall.","Uninstall");
起初我使用的是 m.ReleaseMutex() 而不是 m.Close(),我发现它引发了异常,因为我不拥有互斥锁。 Close 是我应该使用的,只是为了确保我的副本在我再次检查之前已关闭(否则 createNew 永远不会为真,如果第一次不是真的)。
【讨论】:
以上是关于要求卸载前关闭 Winforms 应用程序的主要内容,如果未能解决你的问题,请参考以下文章
在 WinForms 应用程序中呈现 HTML 的最佳方式? [关闭]
哪个日志实用程序适用于 C#(ASP.NET、WinForms)中的 .NET 应用程序? [关闭]