基于 Serilog WPF 的应用程序可以工作,但在作为 EXE 安装时不起作用

Serilog WPF based app works but not when installed as an EXE

提问人:Fletcher Johnson 提问时间:10/16/2021 最后编辑:Fletcher Johnson 更新时间:10/20/2021 访问量:436

问:

注意:这是 Microsoft.Data.SqlClient 及其 SqlConnection 的实现的问题。如果我创建一个实例 (_sqlConnection = new SqlConnection(); ),然后检查状态 ( _sqlConnection.State),我会得到一个 NullReferenceException。如果我分配了有效的连接字符串,则仍为 Null 异常。

解决方案(以节省您的时间)是恢复使用System.Data.SqlClient,一切都很好。我将其余部分留在这里,以防它有助于追踪原因 - 或者如果其他人遇到类似的问题。

我有一个WPF .net 4.7.2应用程序,当我从VS构建和运行时运行(或在调试或发布中双击.exe)。如果我生成一个.msi文件并从那里安装,则在将日志写入MS SQL服务器(但未写入本地文件)时出现空异常错误

我正在使用:

  • 蚕虫:2.10.0
  • Serilog.Sinks.控制台:4.0.0
  • Serilog.Sinks.文件:5.0.0
  • Serilog.Sinks.PeriodicBatching:2.3.0
  • Serilog.Sinks.MSSqlServer:5.6.1
  • 女士。Data.SqlClient:3.0.1
  • System.Data.Common:4.3.0
  • System.Data.SqlClient:4.8.3

.msi 文件是使用以下方法创建的: Microsoft Visual Studio 安装程序项目(可从 https://marketplace.visualstudio.com/items?itemName=VisualStudioClient.MicrosoftVisualStudio2017InstallerProjects&ssr=false#overview 获取)

以下代码已经过修改,以消除所有干扰以及任何专有信息。请记住,除非作为 .msi 文件安装,否则这工作正常。

当我的应用启动时,我调用以下命令: Serilog.Debugging.SelfLog.Enable(msg => Debug.WriteLine(msg));

调用导致问题的示例: LogDebug(“这是 {user} 对 LogDebug 的开发人员测试”, );

法典:

// Primary method
public void LogDebug(string msgtemplate, params object[] parms){
      var LogCfg = GetStdLogConfig();
      Log.Logger = LogCfg.CreateLogger();
      Log.Warning(msgtemplate, parms);
      Log.CloseAndFlush();  // error happens on this line
}  
protected virtual LoggerConfiguration GetStdLogConfig()
{
    LoggerConfiguration logcfg = null;
    logcfg = new LoggerConfiguration()
        .MinimumLevel.ControlledBy(StandardLevelSwitch)
        .Enrich.WithProperty("Fid1", AppValues.VersionNo)
        .Enrich.WithProperty("Fid2", AppValues.UserId)
        .Enrich.WithProperty("Fid3", getUserRightsString())
        .Enrich.WithProperty("Fid4", AppValues.AppCompileMode);

    AddLocalFile(logcfg, "std"); // this writes to local file just fine.
    AddSql(logcfg, "std");

    return logcfg;
}

protected virtual LoggerConfiguration AddSql(LoggerConfiguration logcfg, string mode = "")
{
        try
    {
            var logTable = "App_Logs"; // Renamed for sample
            var sinkOptions = new MSSqlServerSinkOptions { TableName = logTable };
            var columnOptionVals = new ColumnOptions
            {
                AdditionalColumns = new System.Collections.ObjectModel.Collection<SqlColumn>()
            };
            columnOptionVals.AdditionalColumns.Add(new SqlColumn("Fid1", System.Data.SqlDbType.NVarChar, true, 50));
            columnOptionVals.AdditionalColumns.Add(new SqlColumn("Fid2", System.Data.SqlDbType.NVarChar, true, 15));
            columnOptionVals.AdditionalColumns.Add(new SqlColumn("Fid3", System.Data.SqlDbType.NVarChar, true, 100));
            columnOptionVals.AdditionalColumns.Add(new SqlColumn("Fid4", System.Data.SqlDbType.NVarChar, true, 20));
            columnOptionVals.Store.Remove(StandardColumn.MessageTemplate);
            columnOptionVals.LogEvent.DataLength = 2048;
            columnOptionVals.PrimaryKey = columnOptionVals.TimeStamp;
            columnOptionVals.TimeStamp.NonClusteredIndex = true;
            
            // <Valid ConnectionString> is the same as used to do other updates without issue
            logcfg.WriteTo.MSSqlServer(
                connectionString: <Valid ConnectionString>,
                sinkOptions: sinkOptions,
                columnOptions: columnOptionVals
            );
    return logcfg;
}

错误发生在 Log.CloseAndFlush():。

System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=Microsoft.Data.SqlClient
StackTrace:
at Microsoft.Data.SqlClient.SqlConnection.OpenAsync(CancellationToken cancellationToken)

如果我继续,此错误显示:

System.NullReferenceException
HResult=0x80004003
Message=Object reference not set to an instance of an object.
Source=Microsoft.Data.SqlClient
StackTrace:
at Microsoft.Data.SqlClient.SqlConnection.OpenAsync(CancellationToken cancellationToken)

This exception was originally thrown at this call stack:
Microsoft.Data.SqlClient.SqlConnection.OpenAsync(System.Threading.CancellationToken)
System.Data.Common.DbConnection.OpenAsync()
Serilog.Sinks.MSSqlServer.Platform.SqlClient.SqlConnectionWrapper.OpenAsync()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() in exceptionservicescommon.cs

如果我在 StackTrace 中查看此异常,我会注意到其他信息:

在 Microsoft.Data.SqlClient.SqlConnection.OpenAsync(CancellationToken cancellationToken) 在 System.Data.Common.DbConnection.OpenAsync() 在 Serilog.Sinks.MSSqlServer.Platform.SqlClient.SqlConnectionWrapper.d__6.MoveNext() 在 System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() 中 f:\dd\ndp\clr\src\BCL\system\runtime\exceptionservices\exceptionservicescommon.cs:第 133 行

然后它继续(但不会向 SQL Server 记录任何内容)

在输出窗口中,我看到(由于上面的SelfLog调用):

Exception thrown: 'System.NullReferenceException' in mscorlib.dll
Object reference not set to an instance of an object.

当我调试 .exe 时,在实例化 SqlConnection 之后,许多属性都是 NullExceptions,而不是 NULL。尝试为它们赋值不会执行任何操作,它们仍然是 NullExceptions。但它只发生在此调用中,SqlConnection 的所有其他实例化都按预期工作。

解决方案中的所有其他项目都使用 System.Data.SqlClient - 这是所有代码的工作方式,只有此接收器不起作用。

C# WPF NullReferenceException SeriLog System.Data.SqlClient

评论

0赞 Fletcher Johnson 10/16/2021
该错误似乎来自 SqlConnectionWrapper.cs - OpenAsync()。ConfigureAwait(false) - 第 39 行

答:

1赞 Fletcher Johnson 10/20/2021 #1

我根据电子邮件中的打开信息编辑了图书馆。最终修复它的方法(无论是否借助这些步骤)是将 Github MS SQL 库替换为默认的系统 sql 库。

//using Microsoft.Data.SqlClient; 
using System.Data.SqlClient;