升级的winforms应用程序现在获取NullReferenceException调用menuitems PerformClick方法,任何想法?

时间:2013-06-09 16:04:58

标签: c# winforms .net-4.0

背景

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#       [外部代码]

2 个答案:

答案 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以将该方法调用到。