Deploy as single-file in .net5 with log4net throws exception for config-file

7

Trying to deploy a console-application written in .Net 5 with log4net as a single-file. Running deployed application throws exception.

Steps to reproduce

  • dotnet new console --name TestConsole --language C# (make sure .net 5.0)
  • Install-Package 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 (copy always)
<?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>
  • publish (no single file) = works (when running the console application)

dotnet publish -o .\Publish --self-contained true -r win-x64

  • publish (no single file) = throws exception (when running the console application)

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?

c#
deployment
log4net
.net-5
single-file
asked on Stack Overflow Nov 20, 2020 by McClint • edited Nov 20, 2020 by McClint

1 Answer

4

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.

answered on Stack Overflow Nov 28, 2020 by Joshua Hudson

User contributions licensed under CC BY-SA 3.0