C# 升级的winforms应用程序现在正在获取NullReferenceException调用menuitems PerformClick方法,有什么想法吗?
背景: 最初使用.NET 1.1编写的WinForms应用程序通过Visual Studio迁移 从Studio到.NET4.0。主应用程序窗体顶部的典型菜单栏(注意: 未迁移到ToolStripMenuItem),正如您可能预期的那样 包含退出菜单项的文件菜单项 我已经实现了Ctrl-L快捷键,它将打开一个模式锁 形式。我在主窗体上还有一个计时器组件,它将 如果没有活动,则自动打开锁定窗体 可配置的时间量 当显示锁窗体时,您可以解锁(需要用户 再次登录)或退出。如果您选择退出,那么我的代码将执行以下操作: fileExitMenuItem.PerformClick()调用 问题: 由于某种奇怪的原因,在迁移之后如果我退出锁 自动显示或由于Ctrl-L而显示的窗体 然后我在 fileExitMenuItem.PerformClick()代码行 fileExitMenuItem不为空;当抛出异常时使用break 打开后,我可以浏览所有fileExitMenuItems属性 我可以插入表单的设计器代码并观看单击事件 正在连接的处理程序。如果我直接使用文件>>退出菜单项 可以中断事件处理程序中的代码 所以这是一个总的WTF时刻。如有任何建议,我们将不胜感激 [更新1]根据要求,这里有一些代码-每当用户按下Ctrl-L或锁定计时器过期时,就会调用此方法:C# 升级的winforms应用程序现在正在获取NullReferenceException调用menuitems PerformClick方法,有什么想法吗?,c#,winforms,.net-4.0,C#,Winforms,.net 4.0,背景: 最初使用.NET 1.1编写的WinForms应用程序通过Visual Studio迁移 从Studio到.NET4.0。主应用程序窗体顶部的典型菜单栏(注意: 未迁移到ToolStripMenuItem),正如您可能预期的那样 包含退出菜单项的文件菜单项 我已经实现了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();
[UPDATE 2]执行上述行时调用堆栈信息:
[External Code]
Cudos.exe!Cudos.mainForm.LockApplication()行1132+0x10字节C#
Cudos.exe!Cudos.mainForm.fileLockCudosMenuItem\u单击(对象发送方,System.EventArgs e)行1594+0x8字节C#
[外部代码]
Cudos.exe!Cudos.mainForm.Main()行1880+0x1d字节C#
[外部代码]
我不确定,但如果您调用“执行”按钮,我将尝试删除计时器的重新启动。
当由于调用application.Exit()而不再存在应用程序时,可以调用Tick事件
最后,我放弃了,只是通过将fileExitMenuItem.PerformClick()更改为Application.Exit()来攻击它。所以我仍然不知道它为什么会抛出异常,但至少现在可以了。我想如果我在fileExitMenuItem click处理程序中加入更多的逻辑,我只需要记住将其提取到一个方法中,并更新此hack以调用该方法。在尝试关闭应用程序时是否有任何事件执行?例如,登录表单上的表单关闭事件。顺便问一下,在菜单事件中执行的代码是什么?我有一个表单关闭事件处理程序,它检查是否有未保存的更改,如果用户用“是/否/取消”提示的“取消”按钮回答,则取消事件。如果事件未被取消,我的计时器组件将停止。哦,退出菜单项事件处理程序中的代码是对Application.exit()的调用,然后在那里放置一个断点,并跟踪那里发生的情况。为了确保没有提出例外,这个问题看起来像是引用了别人的问题。把你的问题更好地记录下来。发布相关代码段和异常的堆栈跟踪。直到fileExitMenuItem.PerformClick()行上发生异常后,才会运行finally块。我已经删除了finally块(尽管没有任何区别),因为应用程序将在错误被记录后以任何方式关闭,如果没有抛出此异常,它将以任何方式退出。在
环境中更改应用程序。退出。退出(1)
?甚至使用系统。诊断。进程。GetCurrentProcess().Kill()。
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
}