背景
WinForms应用程序,最初用.NET 1.1编写,通过Visual迁移 Studio到.NET 4.0。主应用程序表单顶部的典型菜单栏(注意: 没有迁移到ToolStripMenuItem),正如您可能预期的那样 文件menuitem包含一个Exit菜单项。
我已经实现了Ctrl-L快捷键,它会调出一个模态锁 形成。我还在主表单上有一个计时器组件 如果没有活动,则自动调出锁定表单 可配置的时间量。
当显示锁定表单时,您可以解锁(要求用户使用 再次登录)或退出。如果您选择退出,那么我的代码会执行 fileExitMenuItem.PerformClick()调用。
问题:
出于迁移后的一些奇怪的原因,如果我退出锁定 自动显示或由于Ctrl-L显示的表单 快捷方式然后我得到一个NullReferenceException抛出 fileExitMenuItem.PerformClick()代码行。
fileExitMenuItem不为null;抛出异常时抛出 打开我可以浏览所有fileExitMenuItems属性。
我可以打破表单的设计器代码并观察click事件 处理程序附加。如果我使用文件>>直接退出菜单项我 可以破坏事件处理程序中的代码。
所以这是一个完整的WTF时刻。任何关于看什么的建议都将非常感谢
[更新1]这里要求的是一些代码 - 每当用户按下Ctrl-L或锁定计时器时,就会调用此方法:
private void LockApplication()
{
try
{
// Stop the timer so we don't get any more elapsed events whilst we are waiting
// for a user to respond to the lockdown dialog. In addition stop the callout reminder
// time as once we have locked we don't want that doing it's thing.
lockdownTimer.Stop();
calloutsReminderTimer.Stop();
// Clone the current identity so we can check it later.
var previousIdentity = (CudosIdentity)BOUtilities.CurrentIdentity.Clone();
// Show lockdown form.
System.Windows.Forms.DialogResult result;
using (var lockForm = new Forms.applicationLockedForm())
result = lockForm.ShowDialog(this);
if (result == DialogResult.OK)
{
// Did we unlock with a different login?
if (!previousIdentity.Equals(BOUtilities.CurrentIdentity))
{
// Yes, so lose all changes.
CloseOpenForms();
if (_currentLoadSpec != null)
_currentLoadSpec.CancelContent();
}
RefreshLockTimerSetting(null);
}
else
fileExitMenuItem.PerformClick();
}
catch (Exception ex)
{
Helper.LogError(ex);
}
finally
{
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
}
这是退出菜单项的代码:
private void fileExitMenuItem_Click(object sender, System.EventArgs e)
{
Application.Exit();
}
当调用上面的LockApplication方法中的以下行时,我得到NullReferenceException:
fileExitMenuItem.PerformClick();
[更新2]执行上述行时调用堆栈信息:
[External Code]
Cudos.exe!Cudos.mainForm.LockApplication()第1132行+ 0x10字节C# Cudos.exe!Cudos.mainForm.fileLockCudosMenuItem_Click(object sender,System.EventArgs e)1594行+ 0x8字节C# [外部代码] Cudos.exe!Cudos.mainForm.Main()第1880行+ 0x1d字节C# [外部代码]
答案 0 :(得分:0)
我不确定,但是如果您调用Perform_Click,我会尝试删除计时器的重新启动 当没有应用程序因为您调用Application.Exit()时,可以调用Tick事件。
private void LockApplication()
{
try
{
lockdownTimer.Stop();
calloutsReminderTimer.Stop();
.....
if (result == DialogResult.OK)
{
......
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
else
fileExitMenuItem.PerformClick();
}
catch (Exception ex)
{
Helper.LogError(ex);
lockdownTimer.Start();
calloutsReminderTimer.Start();
}
// remove the finally clause
}
答案 1 :(得分:0)
最后我放弃了,只是通过将fileExitMenuItem.PerformClick()更改为Application.Exit()来攻击它。所以我仍然不知道它为什么抛出异常,但它至少现在有效。我想如果我在fileExitMenuItem单击处理程序中添加更多逻辑,我将只需要记住将其提取到方法中并更新此hack以将该方法调用到。