使用 log4net 在 .net5 中部署为单个文件会引发配置文件异常
Deploy as single-file in .net5 with log4net throws exception for config-file
尝试部署一个用 .Net 5 和 log4net 编写的控制台应用程序作为单个文件。
运行 部署的应用程序抛出异常。
重现步骤
- dotnet new console --name TestConsole --language C#(确保.net 5.0)
- 安装包 log4net
- Program.cs
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure(new FileInfo("log.config"));
var logger = log4net.LogManager.GetLogger("TestLogger");
logger.Info("Hello World!");
}
- log.config(总是复制)
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<logger name="TestLogger">
<level value="ALL" />
<appender-ref ref="console" />
</logger>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level - %message%newline" />
</layout>
</appender>
</log4net>
- 发布(没有单个文件)= 有效(当 运行 控制台应用程序时)
dotnet publish -o .\Publish --self-contained true -r win-x64
- 发布(没有单个文件)= 抛出异常(当 运行 控制台应用程序时)
dotnet publish -o .\Publish --self-contained true -r win-x64 -p:PublishSingleFile=true
抛出异常:
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.IO.FileNotFoundException: Cannot find file. (0x80070002)
at System.Reflection.RuntimeModule.GetFullyQualifiedName()
at System.Reflection.RuntimeModule.get_Name()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.get_AppSettings()
at log4net.Util.SystemInfo.GetAppSetting(String key)
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.IO.FileNotFoundException: Cannot find file. (0x80070002)
at System.Reflection.RuntimeModule.GetFullyQualifiedName()
at System.Reflection.RuntimeModule.get_Name()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.get_AppSettings()
at log4net.Util.SystemInfo.GetAppSetting(String key)
我错过了什么?
所以我认为问题是由于 .NET 5 中的更改引起的。我还假设需要更新 log4net 才能使用新的单一文件格式。
这里讨论了 .NET 5 如何以不同于 3.1 的方式处理单个文件。
https://github.com/dotnet/core/issues/5409#issuecomment-715522029
在 3.1 中,从技术上讲,单个可执行文件被解压缩并 运行 来自临时文件(至少根据我的经验,如果这些文件未在要包含的项目文件中设置,这可能会导致本地引用文件出现问题在单个文件之外)。在 .NET 5 中,他们试图转移到程序集在内存中执行时保留在同一目录中的情况。但是,很明显,这会导致您在 log4net 中发现的其他问题。
上面的 link 让我找到了答案:
dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeAllContentForSelfExtract=true
/p:IncludeAllContentForSelfExtract=true 强制 .NET 5 单个文件的行为与 3.1 完全相同,这对我有用。
我将在接下来的几个月中继续尝试,希望 log4net .NET 5 兼容性开始与新格式一起工作。但至少这个旗帜让我向前迈进了。
尝试部署一个用 .Net 5 和 log4net 编写的控制台应用程序作为单个文件。 运行 部署的应用程序抛出异常。
重现步骤
- dotnet new console --name TestConsole --language C#(确保.net 5.0)
- 安装包 log4net
- Program.cs
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure(new FileInfo("log.config"));
var logger = log4net.LogManager.GetLogger("TestLogger");
logger.Info("Hello World!");
}
- log.config(总是复制)
<?xml version="1.0" encoding="utf-8" ?>
<log4net>
<logger name="TestLogger">
<level value="ALL" />
<appender-ref ref="console" />
</logger>
<appender name="console" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level - %message%newline" />
</layout>
</appender>
</log4net>
- 发布(没有单个文件)= 有效(当 运行 控制台应用程序时)
dotnet publish -o .\Publish --self-contained true -r win-x64
- 发布(没有单个文件)= 抛出异常(当 运行 控制台应用程序时)
dotnet publish -o .\Publish --self-contained true -r win-x64 -p:PublishSingleFile=true
抛出异常:
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.IO.FileNotFoundException: Cannot find file. (0x80070002)
at System.Reflection.RuntimeModule.GetFullyQualifiedName()
at System.Reflection.RuntimeModule.get_Name()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.get_AppSettings()
at log4net.Util.SystemInfo.GetAppSetting(String key)
log4net:ERROR Exception while reading ConfigurationSettings. Check your .config file is well formed XML.
System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
---> System.IO.FileNotFoundException: Cannot find file. (0x80070002)
at System.Reflection.RuntimeModule.GetFullyQualifiedName()
at System.Reflection.RuntimeModule.get_Name()
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.get_ConfigPaths()
at System.Configuration.ClientConfigurationHost.GetStreamName(String configPath)
at System.Configuration.ClientConfigurationHost.get_IsAppConfigHttp()
at System.Configuration.Internal.DelegatingConfigHost.get_IsAppConfigHttp()
at System.Configuration.ClientConfigurationSystem..ctor()
at System.Configuration.ConfigurationManager.EnsureConfigurationSystem()
--- End of inner exception stack trace ---
at System.Configuration.ConfigurationManager.PrepareConfigSystem()
at System.Configuration.ConfigurationManager.GetSection(String sectionName)
at System.Configuration.ConfigurationManager.get_AppSettings()
at log4net.Util.SystemInfo.GetAppSetting(String key)
我错过了什么?
所以我认为问题是由于 .NET 5 中的更改引起的。我还假设需要更新 log4net 才能使用新的单一文件格式。
这里讨论了 .NET 5 如何以不同于 3.1 的方式处理单个文件。
https://github.com/dotnet/core/issues/5409#issuecomment-715522029
在 3.1 中,从技术上讲,单个可执行文件被解压缩并 运行 来自临时文件(至少根据我的经验,如果这些文件未在要包含的项目文件中设置,这可能会导致本地引用文件出现问题在单个文件之外)。在 .NET 5 中,他们试图转移到程序集在内存中执行时保留在同一目录中的情况。但是,很明显,这会导致您在 log4net 中发现的其他问题。
上面的 link 让我找到了答案:
dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeAllContentForSelfExtract=true
/p:IncludeAllContentForSelfExtract=true 强制 .NET 5 单个文件的行为与 3.1 完全相同,这对我有用。
我将在接下来的几个月中继续尝试,希望 log4net .NET 5 兼容性开始与新格式一起工作。但至少这个旗帜让我向前迈进了。