Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ConfigurationManager is not trim compatible #49062

Closed
eerhardt opened this issue Mar 3, 2021 · 15 comments
Closed

ConfigurationManager is not trim compatible #49062

eerhardt opened this issue Mar 3, 2021 · 15 comments
Labels
area-System.Configuration bug linkable-framework Issues associated with delivering a linker friendly framework
Milestone

Comments

@eerhardt
Copy link
Member

eerhardt commented Mar 3, 2021

Using the latest 6.0 SDK

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0-preview.3.21153.4" />
  </ItemGroup>

</Project>
using System;
using System.Configuration;

namespace ConsoleApp7
{
    class Program
    {
        static void Main(string[] args)
        {
            string sAttr = ConfigurationManager.AppSettings.Get("Key0");
            Console.WriteLine("hello" + sAttr);
        }
    }
}
❯ dotnet publish -c Release -r win-x64 -p:PublishTrimmed=true -p:TrimMode=link
❯ C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\bin\Release\net6.0\win-x64\publish\ConsoleApp7.exe
Unhandled exception. System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
 ---> System.MissingMethodException: Cannot dynamically create an instance of type 'System.Configuration.ClientConfigurationHost'. Reason: No parameterless constructor defined.
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Configuration.TypeUtil.CreateInstance(Type type)
   at System.Configuration.Internal.ConfigSystem.System.Configuration.Internal.IConfigSystem.Init(Type typeConfigHost, Object[] hostInitParams)
   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 ConsoleApp7.Program.Main(String[] args) in C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\Program.cs:line 12

Because #48428 marked all assemblies building from dotnet/runtime as IsTrimmable=true, System.Configuration.ConfigurationManager is now getting aggressively trimmed. However, since we haven't addressed the ILLink warnings in the assembly, it is not trim compatible.

We should probably remove IsTrimmable from this assembly until we have addressed its warnings.

cc @marek-safar @sbomer

@ghost
Copy link

ghost commented Mar 3, 2021

Tagging subscribers to this area: @safern
See info in area-owners.md if you want to be subscribed.

Issue Details

Using the latest 6.0 SDK

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0-preview.3.21153.4" />
  </ItemGroup>

</Project>
using System;
using System.Configuration;

namespace ConsoleApp7
{
    class Program
    {
        static void Main(string[] args)
        {
            string sAttr = ConfigurationManager.AppSettings.Get("Key0");
            Console.WriteLine("hello" + sAttr);
        }
    }
}
❯ dotnet publish -c Release -r win-x64 -p:PublishTrimmed=true -p:TrimMode=link
❯ C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\bin\Release\net6.0\win-x64\publish\ConsoleApp7.exe
Unhandled exception. System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
 ---> System.MissingMethodException: Cannot dynamically create an instance of type 'System.Configuration.ClientConfigurationHost'. Reason: No parameterless constructor defined.
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Configuration.TypeUtil.CreateInstance(Type type)
   at System.Configuration.Internal.ConfigSystem.System.Configuration.Internal.IConfigSystem.Init(Type typeConfigHost, Object[] hostInitParams)
   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 ConsoleApp7.Program.Main(String[] args) in C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\Program.cs:line 12

Because #48428 marked all assemblies building from dotnet/runtime as IsTrimmable=true, System.Configuration.ConfigurationManager is now getting aggressively trimmed. However, since we haven't addressed the ILLink warnings in the assembly, it is not trim compatible.

We should probably remove IsTrimmable from this assembly until we have addressed its warnings.

cc @marek-safar @sbomer

Author: eerhardt
Assignees: -
Labels:

area-System.Configuration

Milestone: -

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Mar 3, 2021
@eerhardt eerhardt added the linkable-framework Issues associated with delivering a linker friendly framework label Mar 3, 2021
@ghost
Copy link

ghost commented Mar 3, 2021

Tagging subscribers to 'linkable-framework': @eerhardt, @vitek-karas, @LakshanF, @tannergooding, @sbomer
See info in area-owners.md if you want to be subscribed.

Issue Details

Using the latest 6.0 SDK

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0-preview.3.21153.4" />
  </ItemGroup>

</Project>
using System;
using System.Configuration;

namespace ConsoleApp7
{
    class Program
    {
        static void Main(string[] args)
        {
            string sAttr = ConfigurationManager.AppSettings.Get("Key0");
            Console.WriteLine("hello" + sAttr);
        }
    }
}
❯ dotnet publish -c Release -r win-x64 -p:PublishTrimmed=true -p:TrimMode=link
❯ C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\bin\Release\net6.0\win-x64\publish\ConsoleApp7.exe
Unhandled exception. System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
 ---> System.MissingMethodException: Cannot dynamically create an instance of type 'System.Configuration.ClientConfigurationHost'. Reason: No parameterless constructor defined.
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType rt)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
   at System.Activator.CreateInstance(Type type, Boolean nonPublic)
   at System.Configuration.TypeUtil.CreateInstance(Type type)
   at System.Configuration.Internal.ConfigSystem.System.Configuration.Internal.IConfigSystem.Init(Type typeConfigHost, Object[] hostInitParams)
   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 ConsoleApp7.Program.Main(String[] args) in C:\Users\eerhardt\source\repos\ConsoleApp7\ConsoleApp7\Program.cs:line 12

Because #48428 marked all assemblies building from dotnet/runtime as IsTrimmable=true, System.Configuration.ConfigurationManager is now getting aggressively trimmed. However, since we haven't addressed the ILLink warnings in the assembly, it is not trim compatible.

We should probably remove IsTrimmable from this assembly until we have addressed its warnings.

cc @marek-safar @sbomer

Author: eerhardt
Assignees: -
Labels:

area-System.Configuration, linkable-framework, untriaged

Milestone: -

@marek-safar
Copy link
Contributor

@eerhardt I don't see any linker suppressions in System.Configuration.ConfigurationManager, is that because it's OOB package?

@eerhardt
Copy link
Member Author

eerhardt commented Mar 3, 2021

is that because it's OOB package?

Yes. We only run the linker analysis on the shared framework / runtimepack assemblies currently. #48488 tracks adding analysis for OOB libraries.

@HermanSchoenfeld
Copy link

HermanSchoenfeld commented Dec 1, 2022

This issue is still occurring in .NET 7:

Exception

Unhandled exception. System.Configuration.ConfigurationErrorsException: Configuration system failed to initialize
 ---> System.MissingMethodException: Cannot dynamically create an instance of type 'System.Configuration.ClientConfigurationHost'. Reason: No parameterless constructor defined.
   at System.RuntimeType.ActivatorCache..ctor(RuntimeType)
   at System.RuntimeType.CreateInstanceDefaultCtor(Boolean, Boolean)
   at System.Configuration.Internal.ConfigSystem.System.Configuration.Internal.IConfigSystem.Init(Type, Object[] )
   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)
   at Program.<Main>$(String[]) in D:\Development\XXX\YYY\ConsoleApp1\Program.cs:line 1

Steps to reproduce

  1. Create a Console App targeting .NET 7
  2. Add package System.Configuration.ConfigurationManager (version 7.0.0)
  3. Create a publishing profile
    image
  4. Publish & Run

Environment Details

Visual Studio

Microsoft Visual Studio Community 2022
Version 17.5.0 Preview 1.0
VisualStudio.17.Preview/17.5.0-pre.1.0+33103.201
Microsoft .NET Framework
Version 4.8.04084

@steveharter
Copy link
Member

Verified issue. The repro steps need to call into the config system, so a couple extra steps:

  1. Add an App.config file. For my case I created a ConsoleApp1.config that is copied to bin with the contents:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <trace>
      <listeners>
        <add name="consoleTraceListener" />
      </listeners>
    </trace>
    <sharedListeners>
      <add name="consoleTraceListener" type="System.Diagnostics.ConsoleTraceListener" />
    </sharedListeners>
</configuration>
  1. Call into the config:
var x = System.Configuration.ConfigurationManager.GetSection("system.diagnostics");
Console.WriteLine($"Hello, World! {x}"); // x.ToString() should be "System.Configuration.Configuration"

@ericstj
Copy link
Member

ericstj commented Aug 10, 2023

This assembly isn't close to working with the linker given all it's use of runtime described types from user config files.

The latest version doesn't have the IsTrimmable attribute and works with net6.0. It is, however, broken on net6.0 and net7.0 - because the default changed to trim everything.

I chatted with @eerhardt and he let me know there is not a great way (other than an rd.xml) for the assembly itself to tell the linker to root the entire assembly.

For now you can workaround this with the following in the application:

  <ItemGroup>
    <TrimmerRootAssembly Include="System.Configuration.ConfigurationManager" />
  </ItemGroup>

That works on net6.0 - net8.0. If we ever wanted to do better we'd need to give this assembly linker annotations, but I'm not seeing a need to do that right now. This assembly and its type closure is very large (5.3 MB in my test) and unlikely to be something that folks want to use in a linked application. Moving this to future.

@ericstj ericstj modified the milestones: 8.0.0, Future Aug 10, 2023
@jkotas
Copy link
Member

jkotas commented Aug 10, 2023

For now you can workaround this with the following in the application:

This is not a reliable workaround. There are still going to be situations when the trimmed app is going to be broken, even with this workaround.

@jkotas
Copy link
Member

jkotas commented Aug 10, 2023

I think it should be fine to close this issue. This assembly is not compatible with trimming by design, due to heavy dependency on Type.GetType(string). There is no good way to fix that, without changing the programming model significantly.

@HermanSchoenfeld
Copy link

HermanSchoenfeld commented Aug 15, 2023

The notion that this assembly is unlikely to be used in a linked application is basically saying that linked applications are unlikely to use configuration. In my 20 years of .NET development, I don't think I've ever encountered a single production application, desktop, web, mobile that didn't rely on or use configuration of some sort. The idea that a non-trivial app would not use this assembly I think is an incorrect assessment. If you can't link this assembly then linking isn't going to work for almost all real-world use-cases. Why even bother?

@jkotas
Copy link
Member

jkotas commented Aug 15, 2023

There are several different configuration systems available in .NET. Some are compatible with trimming and AOT and others are not.

ASP.NET Core uses Microsoft.Extensions.Configuration system that is trim and AOT compatible starting with .NET 8 (#44493). If you need compatibility with trimming and AOT, Microsoft.Extensions.Configuration would be the configuration system to use.

@steveharter
Copy link
Member

Closing as by design; not investing in ConfigurationManager.

@HermanSchoenfeld
Copy link

There are several different configuration systems available in .NET. Some are compatible with trimming and AOT and others are not.

ASP.NET Core uses Microsoft.Extensions.Configuration system that is trim and AOT compatible starting with .NET 8 (#44493). If you need compatibility with trimming and AOT, Microsoft.Extensions.Configuration would be the configuration system to use.

Thanks for the info, that seems like a reasonable alternative approach and something I'll invest in. For those looking at native apps, it would be helpful to have a compiled list of "never going to support" assemblies so that we don't waste endless hours trying to get something that supposedly should work to work when it's not going to work "by design".

  1. System.Configuration.ConfigurationManager
  2. ??

@steveharter
Copy link
Member

so that we don't waste endless hours trying to get something that supposedly should work to work when it's not going to work "by design".

Note most of the libraries provide an indication of the investment level through a README.md file located in their src folder.

System.Configuration.ConfigurationManager has a We only consider fixes to maintain or improve quality bar.

Microsoft.Extensions.Configuration has a We consider new features, new APIs, bug fixes, and performance changes bar

@jkotas
Copy link
Member

jkotas commented Aug 20, 2023

For those looking at native apps, it would be helpful to have a compiled list of "never going to support" assemblies so that we don't waste endless hours trying to get something that supposedly should work to work when it's not going to work "by design".

Thank you for the feedback. I like this idea. Submitted doc updates in dotnet/docs#36769 . Please take a look.

@ghost ghost locked as resolved and limited conversation to collaborators Sep 19, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Configuration bug linkable-framework Issues associated with delivering a linker friendly framework
Projects
No open projects
Development

No branches or pull requests

7 participants