C# 升级的winforms应用程序现在正在获取NullReferenceException调用menuitems PerformClick方法,有什么想法吗?

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快捷键,它将打开一个模式锁 形式。我在主窗体上还有一个计时器组件,它将 如果没有活动,则自动打开锁定窗体 可配置的时间量 当显示锁窗体时,您可以解锁(需要用户 再次登录)或退出。如果您选择退出,那么我的代码将执

背景:

最初使用.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或锁定计时器过期时,就会调用此方法:

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

}