要求卸载前关闭 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 的最佳方式? [关闭]

WinForms中的WPF控件[关闭]

哪个日志实用程序适用于 C#(ASP.NET、WinForms)中的 .NET 应用程序? [关闭]

Winforms的多列组合框控件[关闭]

散列或加密或两者都存储用户的密码? C# Winforms [关闭]

如何从另一个应用程序关闭 WPF 系统托盘应用程序?