Keep BAML decompilation working when WPF assemblies are missing - #3876
Merged
Conversation
KnownThings hard-required PresentationFramework, PresentationCore and WindowsBase to be resolvable, so decompiling a WPF binary on a machine without WPF (Linux/macOS) threw "Could not resolve known assembly" and aborted the whole BAML decompile. Mirror MinimalCorlib: when a well-known BAML assembly cannot be resolved, BamlDecompilerTypeSystem substitutes a synthetic stand-in module that upholds the invariant KnownThings assumes. The stand-in only materializes the types the decompiler explicitly seeds, so it stays bounded to the well-known set and references to other types keep degrading to UnknownType exactly as before. For the WPF assemblies it also reproduces the XmlnsDefinitionAttribute mapping so known types still serialize under the presentation xmlns instead of a clr-namespace fallback. Assisted-by: Claude:claude-opus-4-8:Claude Code
Contributor
There was a problem hiding this comment.
Pull request overview
This PR updates the BAML decompiler’s type-system setup so it can continue decompiling WPF BAML when the well-known WPF assemblies (e.g., PresentationFramework) are not resolvable (common on non-Windows machines), by substituting synthetic stand-in modules and reviving/splitting BAML test coverage.
Changes:
- Add a
SyntheticWpfModulefallback and hook it intoBamlDecompilerTypeSystem/KnownThingsto avoid hard failures when WPF assemblies are missing. - Reintroduce and split BAML decompiler tests into platform-agnostic vs Windows-only projects, updating solutions/solution filters accordingly.
- Extend Windows CI to archive the compiled BAML-fixtures assembly and execute the platform-agnostic BAML tests.
Reviewed changes
Copilot reviewed 13 out of 50 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| ILSpy.XPlat.slnf | Includes the platform-agnostic BAML decompiler test project in the xplat solution filter. |
| ILSpy.sln | Adds both BAML decompiler test projects to the main solution. |
| ILSpy.Desktop.slnf | Includes the platform-agnostic BAML decompiler test project in the desktop solution filter. |
| ILSpy.BamlDecompiler.Tests/packages.lock.json | Updates lock file for the platform-agnostic test project’s new TFM/dependency graph. |
| ILSpy.BamlDecompiler.Tests/MissingReferencesTests.cs | Adds regression coverage for decompiling when WPF assemblies are intentionally hidden. |
| ILSpy.BamlDecompiler.Tests/ILSpy.BamlDecompiler.Tests.csproj | Converts the base BAML test project to platform-agnostic (net11.0) and wires references/signing. |
| ILSpy.BamlDecompiler.Tests.Windows/Mocks/AvalonDock.cs | Restores WPF fixture mock types used by round-trip tests. |
| ILSpy.BamlDecompiler.Tests.Windows/ILSpy.BamlDecompiler.Tests.Windows.csproj | Introduces Windows-only test project for WPF XAML→BAML round-trip fixtures. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/SimplePropertyElement.xaml | Adds WPF XAML fixture for property-element serialization cases. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/SimpleNames.xaml.cs | Adds code-behind fixture for name-related XAML cases. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/SimpleNames.xaml | Adds XAML fixture for name/x:Name scenarios. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/SimpleDictionary.xaml | Adds ResourceDictionary fixture. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Simple.xaml.cs | Adds code-behind fixture for a basic Window case. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Simple.xaml | Adds basic Window XAML fixture. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Resources.xaml.cs | Adds code-behind fixture for resource dictionary nesting scenarios. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Resources.xaml | Adds XAML fixture exercising repeated resource scopes. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/ReadonlyProperty.xaml.cs | Adds code-behind fixture for readonly-property related cases. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/ReadonlyProperty.xaml | Adds XAML fixture for readonly property element scenarios. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/NamespacePrefix.xaml | Adds fixture stressing namespace prefix handling and unknown assemblies. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/MyControl.xaml.cs | Adds custom control fixture code-behind used by multiple XAML cases. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/MyControl.xaml | Adds custom control XAML fixture. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/MarkupExtension.xaml | Adds fixture for markup extension parsing/formatting. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue775.xaml | Adds fixture for a historical issue case. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue445.xaml | Adds fixture for a historical issue case involving context menus/resources. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue3318.xaml.cs | Adds code-behind fixture for issue 3318 scenario. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue3318.xaml | Updates fixture assembly-qualified namespace to match the new Windows test assembly name. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue2116.xaml.cs | Adds code-behind fixture for component resource key/static references. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue2116.xaml | Adds fixture for style/resource reference permutations. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue2097.xaml.cs | Adds code-behind fixture for static member usage in XAML. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue2097.xaml | Adds fixture for {x:Static} usage. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue2052.xaml | Adds fixture for x:XmlAttributeProperties.XmlSpace usage. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue1547.xaml.cs | Adds code-behind fixture for style/setter ordering scenarios. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue1547.xaml | Adds fixture for style/setter cases. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue1546.xaml | Adds large ResourceDictionary fixture for serialization coverage. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Issue1435.xaml | Adds fixture covering automation properties/name behaviors. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/EscapeSequence.xaml | Adds fixture for escaped type names, cultures, and formatting. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/Dictionary1.xaml | Adds fixture for color/brush resources and gradients. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/CustomControl.cs | Adds a custom control fixture with an attached property for namespace-prefix tests. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/AvalonDockCommon.xaml | Adds fixture exercising merged dictionaries and component resource keys. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/AvalonDockBrushes.xaml | Adds fixture for resource keys and brushes. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/AttachedEvent.xaml.cs | Adds code-behind fixture for attached event handling. |
| ILSpy.BamlDecompiler.Tests.Windows/Cases/AttachedEvent.xaml | Adds fixture for attached event markup. |
| ILSpy.BamlDecompiler.Tests.Windows/BamlTestRunner.cs | Adds the WPF round-trip test runner that compares decompiled XAML to source fixtures. |
| ILSpy.BamlDecompiler.Tests.Windows/BamlSecurityTests.cs | Adds security/hardening tests to ensure malformed/crafted BAML fails safely. |
| ICSharpCode.BamlDecompiler/SyntheticWpfModule.cs | Introduces the synthetic stand-in module for missing WPF assemblies, including XmlnsDefinitionAttribute mapping. |
| ICSharpCode.BamlDecompiler/Properties/AssemblyInfo.cs | Adds InternalsVisibleTo so the new test project can access required internals. |
| ICSharpCode.BamlDecompiler/BamlDecompilerTypeSystem.cs | Synthesizes missing “default BAML references” as synthetic modules (with presentation-xmlns mapping where applicable). |
| ICSharpCode.BamlDecompiler/Baml/KnownThings.cs | Seeds synthetic modules via RegisterType() so only known types are materialized. |
| .github/workflows/build-ilspy.yml | Archives Windows-built BAML fixture binaries and adds a step to run the platform-agnostic BAML tests (Windows workflow). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
siegfriedpammer
force-pushed
the
fix-baml-missing-wpf-assemblies
branch
from
July 12, 2026 09:21
9c22225 to
57388cc
Compare
The BAML tests were orphaned: in no solution, no CI, and missing their ICSharpCode.BamlDecompiler reference. Revive them split by platform, mirroring ILSpy.Tests / ILSpy.Tests.Windows: ILSpy.BamlDecompiler.Tests (net11.0) holds platform-agnostic tests - including a regression test that decompiles with the WPF assemblies hidden, covering the missing-assembly fix - and ILSpy.BamlDecompiler.Tests.Windows (net11.0-windows) holds the WPF round-trip cases that compile XAML into BAML. Single-TFM projects keep normal lock files; the Windows one declares all RIDs so its lock is generatable and verifiable on any host. Wire the cross-platform project into ILSpy.sln, ILSpy.XPlat.slnf and ILSpy.Desktop.slnf so it builds and runs on the Linux/macOS legs; the Windows project stays in ILSpy.sln (its tests execute in the Windows leg). The Windows job also archives that assembly, whose embedded BAML lets the decompiler be exercised against real BAML on a host without WPF. Assisted-by: Claude:claude-opus-4-8:Claude Code
siegfriedpammer
force-pushed
the
fix-baml-missing-wpf-assemblies
branch
from
July 12, 2026 15:53
57388cc to
de00484
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Decompiling a WPF binary's BAML on a machine without WPF (Linux/macOS) crashed the entire BAML decompile.
KnownThingshard-requiresPresentationFramework,PresentationCoreandWindowsBaseto be resolvable; when they aren't, it throwsCould not resolve known assembly '...'and aborts.Fix
Mirroring
MinimalCorlib: when a well-known BAML assembly can't be resolved,BamlDecompilerTypeSystemsubstitutes a synthetic stand-in module (SyntheticWpfModule) that upholds the invariantKnownThingsassumes.UnknownTypeexactly as before (no behavioural change when the assemblies are present).XmlnsDefinitionAttributemapping, so known types still serialize under the presentation xmlns instead of aclr-namespacefallback.Tests
The BAML tests were orphaned (in no solution, no CI, and missing their
ICSharpCode.BamlDecompilerreference). They are revived and split by platform, mirroringILSpy.Tests/ILSpy.Tests.Windows:ILSpy.BamlDecompiler.Tests(net11.0) — platform-agnostic tests, including a regression test that decompiles with the WPF assemblies hidden. Runs on the Linux/macOS/Windows legs.ILSpy.BamlDecompiler.Tests.Windows(net11.0-windows) — the WPF round-trip cases that compile XAML into BAML. Runs on the Windows leg.Each project is single-TFM, so each keeps a normal committed lock file; the Windows one declares all RIDs so its lock is generatable and verifiable on any host. The Windows job also archives the round-trip assembly (its embedded BAML lets the decompiler be exercised against real BAML on a host without WPF).
🤖 PR opened by an agent (Claude Code) on behalf of @siegfriedpammer.