Skip to content

Recognise a native host as having no configuration system (#162) - #311

Merged
FreeAndNil merged 3 commits into
masterfrom
Feature/162-quiet-app-settings-in-a-native-host
Aug 20, 2026
Merged

Recognise a native host as having no configuration system (#162)#311
FreeAndNil merged 3 commits into
masterfrom
Feature/162-quiet-app-settings-in-a-native-host

Conversation

@FreeAndNil

Copy link
Copy Markdown
Contributor

Fixes #162

In a process that hosts the runtime natively there is no entry assembly for the
configuration system to derive the config file path from, so reading an
application setting fails in ClientConfigPaths with a PlatformNotSupportedException
wrapped in a ConfigurationErrorsException. That matched none of the shapes
IsMissingConfigurationSystem recognised, so log4net blamed the user's config file
and repeated the report for every setting the static constructors read: seven
log4net:ERROR blocks with a stack trace each, at startup, in a well configured
application.

A PlatformNotSupportedException anywhere in the inner exception chain is now
treated as an absent configuration system, the same as the Native AOT case. A
malformed config file cannot produce one, so unlike the FileNotFoundException and
TypeLoadException cases it needs no check on which assembly it came from. The
failure is logged once at debug level and application settings come from
environment variables.

Verified on Windows in a C++ host of the CoreCLR built for the purpose, in a host
that loads the runtime through hostfxr, and in powershell.exe loading a
netstandard2.0 build output: seven error blocks before, none after, and exactly one
debug line with log4net.Internal.Debug on.

FreeAndNil and others added 2 commits August 19, 2026 22:44
In a process that hosts the runtime natively there is no entry assembly for the
configuration system to derive the config file path from, so reading an
application setting fails in ClientConfigPaths with a PlatformNotSupportedException
wrapped in a ConfigurationErrorsException. That matched none of the shapes
IsMissingConfigurationSystem recognised, so log4net blamed the user's config file
and repeated the report for every setting the static constructors read: seven
log4net:ERROR blocks with a stack trace each, at startup, in a well configured
application.

A PlatformNotSupportedException anywhere in the inner exception chain is now
treated as an absent configuration system, the same as the Native AOT case. A
malformed config file cannot produce one, so unlike the FileNotFoundException and
TypeLoadException cases it needs no check on which assembly it came from. The
failure is logged once at debug level and application settings come from
environment variables.

Verified on Windows in a C++ host of the CoreCLR built for the purpose, in a host
that loads the runtime through hostfxr, and in powershell.exe loading a
netstandard2.0 build output: seven error blocks before, none after, and exactly one
debug line with log4net.Internal.Debug on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The unit test for a natively hosted process builds the exception by hand, so it
asserts what we believe the configuration system does rather than what it does.
This adds a check that removes the entry assembly for real and reports what
log4net writes while starting up, in the project that already exists to record
what log4net can do in an unusual host.

It cannot be one of the probes in the list: the configuration system caches its
initialization and log4net reads its first application setting from a static
constructor, so by the time any probe runs the outcome is already decided. The
check therefore owns the process from its first statement and the runner selects
it with an argument.

Verified in both directions: it passes as committed, and reverting the
PlatformNotSupportedException case makes it exit non-zero and print the seven
error blocks it captured.

JIT compiled only, deliberately. Native AOT trims the configuration system away,
so the first setting read there fails as a missing constructor long before it can
fail for want of an entry assembly: the published executable passes this check
even with the fix reverted, which would be a green that cannot fail for the
reason the check exists. The reason is recorded next to the CI step and on the
class, so it does not get added back for symmetry.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@FreeAndNil FreeAndNil added this to the 3.4.1 milestone Aug 19, 2026
Every test method, the fixture hooks and the layout factories now carry a
summary saying what they assert, as does the converter that feeds arbitrary
names to NamedPatternConverter. The factories note that
DynamicPatternLayoutTest inherits this fixture and reruns the whole suite
against a DynamicPatternLayout, which is not obvious from either file.

The conditional using directive that came with it keeps System.Linq out of the
net462 compilation, where nothing uses it, which clears an IDE0005 warning.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@FreeAndNil
FreeAndNil force-pushed the Feature/162-quiet-app-settings-in-a-native-host branch from 633d028 to 36aa1ed Compare August 19, 2026 20:56
@FreeAndNil
FreeAndNil merged commit 8bb9233 into master Aug 20, 2026
3 checks passed
@FreeAndNil
FreeAndNil deleted the Feature/162-quiet-app-settings-in-a-native-host branch August 20, 2026 05:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PlatformNotSupportedExceptions when loading log4net

2 participants