Skip to content

Package ijwhost.dll as native asset for self-contained publish#11664

Open
mmanolova-msft wants to merge 1 commit into
dotnet:mainfrom
mmanolova-msft:fix/include-ijwhost-in-publish
Open

Package ijwhost.dll as native asset for self-contained publish#11664
mmanolova-msft wants to merge 1 commit into
dotnet:mainfrom
mmanolova-msft:fix/include-ijwhost-in-publish

Conversation

@mmanolova-msft
Copy link
Copy Markdown

@mmanolova-msft mmanolova-msft commented May 26, 2026

Fixes #11651

Main PR: N/A (this is the main branch fix)

Description

After PR #11575 migrated C++/CLI projects from /clr:pure to /clr:NetCore, DirectWriteForwarder.dll and System.Printing.dll became mixed-mode assemblies requiring ijwhost.dll at runtime. The build was placing ijwhost.dll in the managed lib/net11.0/ folder (via the $(OutDir)*.dll glob), where it is not recognized by RuntimeList.xml. This caused it to be missing from self-contained publish output.

The fix excludes ijwhost.dll from lib/ folder packaging and adds a target to place it in runtimes/win-{arch}/native/ where it is properly listed in the runtime pack manifest.

Customer Impact

Any WPF app published as self-contained (dotnet publish -r win-x64 --self-contained) crashes on launch with:

System.IO.FileNotFoundException: Could not load file or assembly '...\DirectWriteForwarder.dll'.
The specified module could not be found.

Framework-dependent apps are unaffected (they load from the shared framework folder).

Regression

Yes. Introduced by #11575 (Remove /clr:pure from WPF C++/CLI projects), which shipped in SDK 11.0.100-preview.5.26264.105. Not present in 11.0.100-preview.5.26263.112.

Testing

  • Installed both SDK versions and confirmed the regression
  • Built WPF with the fix (build.cmd -c Release -platform x64 -pack)
  • Verified ijwhost.dll lands in runtimes/win-x64/native/ (not lib/net11.0/)
  • Patched the runtime pack in NuGet cache and confirmed dotnet publish --self-contained includes Ijwhost.dll in output
  • Ran the published WPF app successfully

Risk

Low. The change only affects packaging of ijwhost.dll — moving it from an incorrect location (lib/) to the correct one (native/). This matches how all other native DLLs (vcruntime140_cor3.dll, wpfgfx_cor3.dll, etc.) are already packaged.

Microsoft Reviewers: Open in CodeFlow

After the /clr:pure to /clr:NetCore migration (dotnet#11575), DirectWriteForwarder
and System.Printing became mixed-mode C++/CLI assemblies that require
ijwhost.dll at runtime. The DLL was being placed in the managed lib/ folder
where it is not recognized by RuntimeList.xml, causing it to be missing from
self-contained publish output.

Exclude ijwhost.dll from the lib/ packaging and add it as a native asset
under runtimes/win-{arch}/native/ so it is properly included in the runtime
pack manifest.

Fixes dotnet#11651

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@mmanolova-msft mmanolova-msft requested review from a team and Copilot May 26, 2026 09:49
@dotnet-policy-service dotnet-policy-service Bot added the PR metadata: Label to tag PRs, to facilitate with triage label May 26, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression in WPF self-contained publish by ensuring ijwhost.dll (required to load IJW mixed-mode C++/CLI assemblies) is packaged as a native runtime asset rather than ending up under the managed lib/ folder, which prevents it from being picked up for self-contained publish.

Changes:

  • Excludes ijwhost.dll from the default $(OutDir)*.dll managed (lib/) packaging glob.
  • Adds a packaging target in both mixed-mode projects to include ijwhost.dll under runtimes/win-{arch}/native/.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Microsoft.DotNet.Wpf/src/System.Printing/System.Printing.vcxproj Excludes ijwhost.dll from lib/ packaging and adds it as a native runtime asset under runtimes/win-{arch}/native/.
src/Microsoft.DotNet.Wpf/src/DirectWriteForwarder/DirectWriteForwarder.vcxproj Same packaging adjustment as System.Printing to ensure ijwhost.dll is treated as a native asset for self-contained publish.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@mmanolova-msft
Copy link
Copy Markdown
Author

@dotnet-policy-service agree company="Microsoft"

nagilson added a commit to dotnet/sdk that referenced this pull request May 28, 2026
Self-contained WPF apps crash due to missing ijwhost.dll.
The fix is tracked in dotnet/wpf#11664.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@vinnarayana-msft
Copy link
Copy Markdown
Contributor

⚠️ Additional Regression: Single-File Publish (PublishSingleFile=true)

This PR correctly fixes the self-contained publish regression by routing ijwhost.dll to runtimes/win-{arch}/native/. However, there's a separate regression with single-file publish that isn't covered here.

Problem

After the /clr:pure/clr:netcore migration, DirectWriteForwarder.dll and System.Printing.dll are now IJW (mixed-mode) assemblies. In single-file publish, they are bundled inside the exe and the runtime attempts to load them from memory. IJW assemblies cannot be loaded from memory — they require the OS LoadLibrary call (because they have a native DllMain entry point, VTableFixups, and PE imports like ijwhost.dll).

Evidence

  1. Verified locally: Single-file publish of a WPF app on preview.4 SDK bundles DirectWriteForwarder.dll inside the exe (not extracted alongside it). Only native DLLs (wpfgfx_cor3.dll, PenImc_cor3.dll, etc.) are extracted.

  2. RuntimeList.xml (from microsoft.windowsdesktop.app.runtime.win-x64 NuGet pack):

    <File Type="Managed" Path="runtimes/win-x64/lib/net11.0/DirectWriteForwarder.dll" ... />
    <File Type="Managed" Path="runtimes/win-x64/lib/net11.0/System.Printing.dll" ... />

    Type="Managed" = bundled inside the exe in single-file mode.

  3. Bundler logic (Bundler.cs): IsAssembly() checks CorHeader != null → IJW assemblies have a CorHeader → classified as FileType.Assembly → always bundled (never excluded).

  4. Microsoft docs (Single-file deployment overview): "Managed C++ components aren't well suited for single file deployment."

Why This Will Crash

  • Single-file host loads Type="Managed" assemblies from memory (no physical file on disk)
  • IJW assemblies need LoadLibrary → requires a physical DLL file
  • IJW initialization requires ijwhost.dll to intercept the load
  • Result: FileNotFoundException or BadImageFormatException at runtime

Fix Required

This needs a change in the dotnet/windowsdesktop repo (not WPF), since that's where RuntimeList.xml is generated. In Microsoft.WindowsDesktop.App.Runtime.sfxproj:

<FrameworkListFileClass Include="DirectWriteForwarder" Profile="WPF" DropFromSingleFile="true" />
<FrameworkListFileClass Include="System.Printing" Profile="WPF" DropFromSingleFile="true" />

DropFromSingleFile="true" forces these DLLs to be extracted alongside the exe (not bundled) — the same behavior as wpfgfx_cor3.dll, PenImc_cor3.dll, and other native WPF dependencies.

Note: We can't use the same native/ folder trick used for ijwhost.dll here, because these DLLs contain managed types (e.g., System.Printing.PrintQueue) that the assembly resolver needs to find in lib/.

Summary

Scenario This PR fixes? Additional fix needed?
Self-contained publish ✅ Yes
Framework-dependent ✅ N/A (never broken)
Single-file publish ❌ No DropFromSingleFile="true" in dotnet/windowsdesktop sfxproj

@mmanolova-msft please validate this once. The changes you made for self-contained looks good.

DonnaChen888 pushed a commit to dotnet/sdk that referenced this pull request May 29, 2026
Self-contained WPF apps crash due to missing ijwhost.dll.
The fix is tracked in dotnet/wpf#11664.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Included in test pass PR metadata: Label to tag PRs, to facilitate with triage Status:Proposed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[NETSDKE2E] With NET11.0.100-preview.5.26264.105 SDK installed, WPF application which is generated by self-contained publish cannot run successfully.

3 participants