wpf: Published SelfContained WPF app with PublishTrimmed option set to True fails with Unhandled Exception

Issue Description

Published WPF .Net Core app using MSBuild 16.8.3+39993bd9d for .NET with options PublishTrimmed=True and SelfContained=True fails with Unhandled Exception.

The same app published with MsBuild 16.4.0 and same options works fine.

Steps to Reproduce

Use WPF (.Net) template from Visual Studio templates, change .csproj file to:

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.1</TargetFramework>
    <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
    <UseWPF>true</UseWPF>
    <PublishTrimmed>true</PublishTrimmed>
    <PublishSingleFile>true</PublishSingleFile>
  </PropertyGroup>
 <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="dotnet publish $(ProjectFileName) --configuration $(ConfigurationName) --framework netcoreapp3.1 --self-contained --runtime win7-x64 --no-build --output .\bin\SCD\$(ConfigurationName)" />
  </Target>
</Project>

Build project, try to run .exe file located in ProjectMainDirectory/bin/SCD/Debug

Expected Behavior

Published application works after trimming operation like it was after publish with MSBuild 16.4.0

Actual Behavior

Unhandled exception thrown.

Can be captured with adding below code to App class in App.xaml.cs file:

        protected override void OnStartup(StartupEventArgs e)
        {
            Current.DispatcherUnhandledException += DisplayUnhandledException; 
            this.DispatcherUnhandledException += DisplayUnhandledException; 
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            base.OnStartup(e);
        }

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show($"Unhandled exception captured. IsTerminating: {e.IsTerminating}");
        }

        private void DisplayUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MessageBox.Show("Unhandled exception captured: " + e.Exception.Message);
        } 

Analysis

Main issue is probably missing assembly, but why the same app published with older MSBuild works fine? Any breaking changes?

It complains about missing assembly: FileNotFoundException: Could not load file or assembly ‘System.Diagnostics.Debug, Version=4.1.2.0’

Problem occurs in Debug and Release configuration.

Versions & Configurations

MSBuild version: 16.8.3+39993bd9d for .NET Visual Studio version: 16.8.3 dotnet --version: 5.0.102

Last working configuration: MSBuild version: 16.4.0+e901037fe dotnet --version: 3.1.101

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 18 (15 by maintainers)

Most upvoted comments

WPF does not support Trimming. There is now an error when compiling on .NET 6.0.

Hey @Symbai,

Here’s one that works for link mode:

Content of the csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
    <TrimMode>link</TrimMode>
  </PropertyGroup>

  <ItemGroup>
    <TrimmerRootAssembly Include="System.Collections" />
    <TrimmerRootAssembly Include="System.Runtime" />
    <TrimmerRootAssembly Include="System.Runtime.Extensions" />
    <TrimmerRootAssembly Include="System.Runtime.InteropServices" />
    <TrimmerRootAssembly Include="System.Runtime.CompilerServices.VisualC" />
    <TrimmerRootDescriptor Include="TrimmerRoots.xml" />
  </ItemGroup>

</Project>
Content of TrimmerRoots.xml
<?xml version="1.0" encoding="utf-8" ?>
<linker>
  <assembly fullname="System.Private.CoreLib">
    <type fullname="System.AppDomain" />
    <type fullname="System.Attribute" />
    <type fullname="System.Reflection.Module" />
    <type fullname="System.Runtime.CompilerServices.IsConst" />
    <type fullname="System.Runtime.CompilerServices.RuntimeHelpers" />
    <type fullname="System.Runtime.InteropServices.CriticalHandle" />
    <type fullname="System.Runtime.InteropServices.GCHandle" />
    <type fullname="System.Runtime.InteropServices.Marshal" />
    <type fullname="System.Security.SecurityCriticalAttribute" />
    <type fullname="System.Security.SuppressUnmanagedCodeSecurityAttribute" />
  </assembly>
</linker>

Beware that your mileage may vary. I only tested it with a simple window with a textbox.

Most of the content in TrimmerRoots.xml is required because the analysis of C++/CLI is not yet supported (See https://github.com/mono/linker/issues/676).