【问题标题】:How to fix NullReferenceException occurring only on some computers如何修复仅在某些计算机上发生的 NullReferenceException
【发布时间】:2020-09-12 19:38:10
【问题描述】:

我使用 VS 2017 安装程序创建了一个 winform 应用程序的安装文件。当我在我的电脑上测试这个设置文件时,登录运行良好。所以我在其他电脑上运行这个安装文件。

但是,当我在这些 PC 上登录应用程序时,应用程序说“对象引用未设置为对象的实例”,尽管我确信数据库中的用户名和密码是正确的。

我见过What is a NullReferenceException, and how do I fix it?,但我不认为这是空异常,因为安装的应用程序没有在我的电脑中抛出上述错误。仅当我在其他 PC 上安装该应用程序时才会出现此错误。

我还尝试将其他 PC 中已安装应用程序文件夹中的 .exe 和 .config 文件替换为我 PC 中应用程序的相同文件(效果很好),并且应用程序运行正常。但后来我重新启动那些电脑,并尝试登录应用程序,同样的错误发生了。

这是登录代码。我相信我已经正确检查了 null 异常。我说的对吗?

private void btnLogin_Click(object sender, EventArgs e)
    {
        try
        {
            var info = UsersBiz.Login(txtUserName.Text.Trim(), txtPassWord.Text);

            if (info != null && info.user.Id > 0)
            {
                Constants.USERINFO = info;

                this.Hide();
                var frm = new frmMain();
                frm.Show();

                if (ckbRemember.Checked)
                {
                    ManagementInventory.Properties.Settings.Default.User = txtUserName.Text;
                    ManagementInventory.Properties.Settings.Default.Pass = txtPassWord.Text;
                    ManagementInventory.Properties.Settings.Default.Save();
                }
            }
            else
            {
                MessageBox.Show("UserName or Password not correct!");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

【问题讨论】:

  • “但我不认为它是空异常” - 除了自己故意抛出这个异常之外,它的原因只有一个:某些东西是空的。在您的情况下,这意味着其中之一为空:UsersBiz(如果不是静态的)、txtUserNametxtUserName.TexttxtPasswordinfoinfo.userchkbRememberManagementInventoryManagementInventory.Properties,或ManagementInventory.SettingsManagementInventory.Properties.Settings.Default
  • 因为它是 WinForms,我希望 UI 组件已经分配了值,并且这些组件中的文本在最坏的情况下是一个空字符串。对我来说,上面代码中的可能可能性是info.user 为空,或者ManagementInventory.Properties.Settings.Default 链中的某些东西是null。我想知道您的设置文件是否有问题(不存在或不在正确的目录中)。您要查找的文件与您的程序文件名相同(例如app.exe),但附加了.configapp.exe.config
  • 此类问题是大多数程序执行某种日志记录的原因。作为一种快速解决方案,您可以将MessageBox.Show(ex.Message) 替换为MessageBox.Show(ex.ToString());然后您可以看到引发异常的确切位置,包括调用堆栈。
  • 我试过MessageBox.Show(ex.ToString()),它指向UserBiz.Login方法中的GetConnectionString方法(连接数据库)。我会看看GetConnectionString 方法或app.config 中的ConnectionString 是否有问题。奇怪的是,如果我从计算机中的应用程序文件夹中复制 app.exeapp.exe.config(运行良好)并粘贴到该应用程序无法运行的计算中,该应用程序将运行良好,直到我重新启动该计算机(问题再次出现) .谢谢你的建议。
  • See this answer for some ideas。您一定缺少运行时或类似的东西。或许请参阅“通用技巧?” 部分。

标签: c# winforms windows-installer


【解决方案1】:

最简单的方法是在程序运行的计算机上使用 Visual Studio 调试器。如果该计算机上没有 Visual Studio,请考虑使用远程调试。见how to start debugging on a remote computer

如果出于安全原因无法进行远程调试,请考虑记录异常,尤其是堆栈跟踪。如果你知道它发生在哪里,只需用 try-catch 包围它

try
{
    // Here are the statements that cause your ArgumentNullException
}
catch (ArgumentNullException exc)
{
    // log the exception
}

如果您的程序没有日志记录工具,请考虑添加类似 NLOG 的内容。另一种可能性是将其附加到文本文件中。

void WriteExceptionToTextFile(Exception exc, string fileName)
{
    using (var writer = File.AppendText(fileName))
    {
        writer.WriteLine("Exception {0}", exc.GetType());
        write.WriteLine("Stack trace" + exc.StackTrace);
        ... // etc
    }
}

如果您不知道异常发生在哪里,则无法尝试捕获它。在这种情况下,请考虑捕获未处理的异常并记录它:

见:catching unhandled exception

在您的表单程序中有一个文件 program.cs,其中包含主要内容:

public static void Main()
{
    AppDomain currentDomain = AppDomain.CurrentDomain;
    currentDomain.UnhandledException += OnUnhandledException;
    ...
}

static void OnUnhandledException(object sender, UnhandledExceptionEventArgs args)
{
    Exception undhandledException = (Exception) args.ExceptionObject;
    // TODO log the unhandled exception

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2015-02-07
    • 2011-11-04
    • 1970-01-01
    • 2017-08-12
    • 2017-09-01
    • 2015-02-03
    相关资源
    最近更新 更多