Vla*_*zki 4 c# forms dispose winforms c#-4.0
我有一个在 .NET Framework 4.0 上运行的 C# WinForms 应用程序。
当用户在一段时间内处于非活动状态时,我希望它隐藏所有显示的表单并在通知区域中显示一个图标。当用户单击该图标时,会出现一个登录表单,如果凭据有效,它将打开之前打开的表单。
为此,我将打开的表单列表存储在List
对象中Form
并隐藏它们,如下所示。该方法由Timer调用:
private void LogOut()
{
foreach (Form form in Application.OpenForms)
if (form.Visible)
{
GlobalVariables.formList.Add(form);
form.Hide();
}
}
Run Code Online (Sandbox Code Playgroud)
验证凭据后,我尝试使表单再次可见,如下所示:
//Show the previous forms.
foreach (Form form in GlobalVariables.formList)
form.Visible = true;
//Clear the forms list.
GlobalVariables.formList.Clear();
Run Code Online (Sandbox Code Playgroud)
如果我在隐藏表单时只打开 MainForm,则在重新登录时它会正常显示。如果我打开任何其他表单(从 MainForm 打开ShowDialog()
),程序将崩溃form.Visible = true;
并给出以下信息错误信息:
ObjectDisposedException was unhandled
Cannot access a disposed object
Run Code Online (Sandbox Code Playgroud)
我该如何解决这个问题?另一种实现我想要实现的目标的方法也很棒。
请注意,使用 try - catch 块来确定表单是否已被处理并重新启动表单不是一个选项,因为用户可能在隐藏表单中具有未保存的输入。
经过 3 个多小时的搜索,我无法在网上找到任何相关内容,因此我们将不胜感激!
编辑:在尝试了各种方法之后,我注意到问题只发生在我使用打开表单的表单上ShowDialog()
。如果我只使用打开的表单Show()
,则一切正常。
但就我而言,使用Show()
不是一个选项,因为我无法让用户单击父表单中的内容。隐藏父表单也不是一个选择,因为他需要查看父表单中的信息。
显然,隐藏表单比您想象的更有影响力。您的代码参与了 Microsoft 对 Winforms 进行的安全审查。非常彻底,在其行为方式中通常不可见,但在源代码中非常明显。施加的一项规则是用户永远不应该失去对应用程序的控制。
这样对话就很麻烦了。核心问题是 ShowDialog() 创建一个模式窗口,该窗口禁用所有其他窗口。这为恶意软件创造了机会,很容易被利用,它所要做的就是隐藏一个对话框,然后你就可以欺骗用户了。用户无法再次获得应用程序的控制权。已启用的一个窗口被隐藏,用户无法再次重新激活它。所有其他窗口都被禁用,因此尝试单击它们或其任务栏按钮将不会产生任何效果。剩下的就是用户使用任务管理器来终止该应用程序。如果用户帐户被锁定,那么这也不是一个选择。
我现在可以听到你结结巴巴地说:“但是,但是,隐藏对话框的是我的代码,而不是恶意软件!” 这不是 Windows 中的工作方式,无法判断这实际上是您的代码完成的。不仅因为它可以注入代码,而且它甚至不必是在您的进程中运行的代码。 任何代码都可以做到这一点,它是 winapi 的一部分。
因此,Winforms 中内置了针对此问题的具体对策,如果在对话框模式下操作时隐藏了窗体,它将自动关闭该窗体。这当然会产生很大的影响,在 ShowDialog() 调用之后编写的代码现在将运行。一切皆有可能,但在你的情况下,一个肯定会发生的事故是,这会处理另一个窗口,并且尝试恢复它将会失败。
这里的粗略指导是你做错了。您正尝试在已经高度安全且经过严格测试的系统之上构建一个安全系统。而且风险很大,自己处理密码是一个很好的方法,会让整个系统的安全性大大降低。普通用户当然会喜欢选择与登录 Windows 时相同的密码。使攻击者更容易获取该密码。
请改为调用LockWorkStation()。
归档时间: |
|
查看次数: |
3831 次 |
最近记录: |