Trying to deploy a console-application written in .Net 5 with log4net as a single-file. Running deployed application throws exception.
Steps to reproduce
static void Main(string[] args)
{
log4net.Config.XmlConfigurator.Configure(new FileInfo("log.config"));
var logger = log4net.LogManager.GetLogger("TestLogger");
logger.Info("Hello World!");
}
<?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
excpetion thrown:
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)
What have I missed?
Now, add the section "<log4net></log4net>" after the <configSections/> element in your app. config file. Next, inside the "<log4net></log4net>" section, place the configuration details as shown in the code snippet given below. That's all you need to do to configure log4net.
So I believe the issue is due to a change in .NET 5. I'm also assuming log4net will need to be updated to work with the new single file format.
There is a discussion here about how .NET 5 handles single files differently than 3.1.
https://github.com/dotnet/core/issues/5409#issuecomment-715522029
In 3.1, technically the single executable gets unzipped and ran from temp (which could cause issues with local referenced files as least in my experience, if those files were not set in the project file to be included outside the single file). In .NET 5 they were trying to move to a case where the assembly stayed in the same directory when executed into memory. However, clearly, this causes other issues as you found with log4net.
This link above put me on to the answer:
dotnet publish -r win-x64 /p:PublishSingleFile=true /p:IncludeAllContentForSelfExtract=true
The /p:IncludeAllContentForSelfExtract=true forces .NET 5 single files to act exactly the same as 3.1 and is what worked for me.
I'll keep trying over the next few months with the hope that log4net .NET 5 compatibility starts working with the new format. But at least this flag let me move foward.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With