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

.NET Core 3.0 WPF app crashing after using illink #595

Closed
tomrus88 opened this issue May 30, 2019 · 18 comments
Closed

.NET Core 3.0 WPF app crashing after using illink #595

tomrus88 opened this issue May 30, 2019 · 18 comments

Comments

@tomrus88
Copy link

tomrus88 commented May 30, 2019

Create and publish WPF app

dotnet new wpf -o wpfapp1
cd wpfapp1
dotnet publish -c Release -r win-x64 /p:PublishTrimmed=true /p:PublishSingleFile=true

Run published app and see it crashing with following error (without PublishTrimmed switch app works fine)

Application: wpfapp1.exe
CoreCLR Version: 4.700.19.28001
.NET Core Version: 3.0.0-preview6-27730-01
Description: The process was terminated due to an unhandled exception.
Exception Info: System.Windows.Markup.XamlParseException: The method or operation is not implemented. ---> System.NotImplementedException: The method or operation is not implemented.
   at System.Windows.Baml2006.Baml2006SchemaContext.ResolveBamlType(BamlType bamlType, Int16 typeId)
   at System.Windows.Baml2006.Baml2006SchemaContext.GetXamlType(Int16 typeId)
   at System.Windows.Baml2006.Baml2006Reader.Process_ElementStart()
   at System.Windows.Baml2006.Baml2006Reader.Process_OneBamlRecord()
   at System.Windows.Baml2006.Baml2006Reader.Process_BamlRecords()
   at System.Windows.Baml2006.Baml2006Reader.Read()
   at System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader, XamlObjectWriter xamlWriter, Boolean onlyLoadOneNode, Boolean skipJournaledProperties, Boolean shouldPassLineNumberInfo, IXamlLineInfo xamlLineInfo, IXamlLineInfoConsumer xamlLineInfoConsumer, XamlContextStack`1 stack, IStyleConnector styleConnector)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   --- End of inner exception stack trace ---
   at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
   at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
   at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
   at System.Windows.Application.LoadBamlStreamWithSyncInfo(Stream stream, ParserContext pc)
   at System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean bSkipJournaledProperties)
   at System.Windows.Application.DoStartup()
   at System.Windows.Application.<.ctor>b__1_0(Object unused)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at wpfapp1.App.Main()
@sbomer
Copy link
Member

sbomer commented May 30, 2019

Thanks for the report @tomrus88. This should be fixed in the next preview, where we're making the default a bit more conservative, but you're likely to see other issues similar to this due to missing analysis for more complex apps. I'll keep this issue open until we get a build with the fix.

@Lakritzator
Copy link

Lakritzator commented Jun 3, 2019

Using dotnet core 3.0.100-preview6-012162
When I try to use /p:PublishTrimmed=true /p:PublishSingleFile=true I get the following error:

---------------------------
Greenshot.exe
---------------------------
Error:
  An assembly specified in the application dependencies manifest (Greenshot.deps.json) was not found:
    package: 'Greenshot.Addon.ExternalCommand', version: '1.0.0'
    path: 'Greenshot.Addon.ExternalCommand.dll'

---------------------------
OK   
---------------------------

Which makes sense, the Greenshot.Addon.ExternalCommand.dll file (and some others) is not in the extracted directory (the Greenshot.Addon.ExternalCommand.dll.config is!!).

It works fine without PublishTrimmed enabled. I need to add that although the main Greenshot csproj references addon projects there is no direct code dependency to them, it's done via reflection and dependency injection. Can I mark projects/assemblies somehow so they are not trimmed?

@sbomer
Copy link
Member

sbomer commented Jun 3, 2019

The linker isn't catching your use of reflection. We'll have docs for solving these kinds of problems soon. In the meantime, try adding the following to your project:

<ItemGroup>
  <TrimmerRootAssembly Include="Greenshot.Addon.ExternalCommand" />
</ItemGroup>

edit: I should have mentioned earlier - there are a few more changes incoming that will basically do the above for you for non-framework assemblies (i.e., the default will be pretty conservative). We will probably get a build later today with that behavior (waiting for dotnet/installer#2236 to merge).

@Lakritzator
Copy link

@sbomer Thanks for the hint, but this somehow doesn't work.

I also tried specifying true via the Directory.Build.props and with the information here: https://github.com/dotnet/standard/blob/release/2.0.0/Microsoft.Packaging.Tools.Trimming/docs/trimming.md

I can look at the next build, and it would be nice if things work out of the box. But would like to be able to control this...

@sbomer
Copy link
Member

sbomer commented Jun 3, 2019

@Lakritzator my apologies, I initially wrote the above thinking that the change had made it in. The PR I linked has the change that enables use of TrimmerRootAssembly and also the more conservative defaults. I appreciate your patience while we wait for the next build...

@Lakritzator
Copy link

@sbomer no problem 😄 it comes when it comes.

The only thing I would like to know, is how to figure out what issues / PRs are in which dotnet core version. Even when something is closed or merged, it doesn't mean that I can download and install it...
This might be something to consider for when the first release candidates are being created.

Lakritzator added a commit to greenshot/greenshot that referenced this issue Jun 4, 2019
@Lakritzator
Copy link

With 3.0.100-preview7-012260 the result already looks a lot better 😄, though it's a lot bigger as it was before (which makes sense but still 😢 )

Still there are issues, I currently get an error as netstandard.dll is missing.
I copied the missing netstandard.dll into the extracted directory under %LOCALAPPDATA%\Temp.net\Greenshot and afterwards the application starts.
The workaround for this is to add the following to my main project <TrimmerRootAssembly Include="netstandard" />

As long as I use Windows Forms, all is okay, but as soon as System.Windows.Media.FontFamily comes into play I get exceptions like:

************** Exception Text **************
System.InvalidCastException: Specified cast is not valid.
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
   at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr)
   at MS.Internal.Text.TextInterface.Factory.Initialize(FactoryType factoryType)
   at MS.Internal.Text.TextInterface.Factory..ctor(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.Text.TextInterface.Factory.Create(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.FontCache.DWriteFactory..cctor()

Or (depending from where I come):

System.TypeInitializationException
  HResult=0x80131534
  Message=The type initializer for 'System.Windows.Media.FontFamily' threw an exception.
  Source=PresentationCore
  StackTrace:
   at System.Windows.Media.Typeface..ctor(FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch)
   at MS.Internal.Text.DynamicPropertyReader.GetTypeface(DependencyObject element)
   at MS.Internal.Text.TextProperties.InitCommon(DependencyObject target)
   at MS.Internal.Text.TextProperties..ctor(FrameworkElement target, Boolean isTypographyDefaultValue)
   at System.Windows.Controls.TextBlock.GetLineProperties()
   at System.Windows.Controls.TextBlock.EnsureTextBlockCache()
   at System.Windows.Controls.TextBlock.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Control.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.StackPanel.StackMeasureHelper(IStackMeasure measureElement, IStackMeasureScrollData scrollData, Size constraint)
   at System.Windows.Controls.StackPanel.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ItemsPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Control.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
   at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Window.MeasureOverrideHelper(Size constraint)
   at System.Windows.Window.MeasureOverride(Size availableSize)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.ContextLayoutManager.UpdateLayout()
   at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
   at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
   at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
   at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
   at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
   at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
   at System.Windows.Forms.Application.RunDialog(Form form)
   at System.Windows.Forms.Form.ShowDialog(IWin32Window owner)
   at System.Windows.Forms.Form.ShowDialog()
   at System.Windows.Forms.Application.ThreadContext.OnThreadException(Exception t)
   at System.Windows.Forms.Application.OnThreadException(Exception t)
   at System.Windows.Forms.Control.WndProcException(Exception e)
   at System.Windows.Forms.Control.ControlNativeWindow.OnThreadException(Exception e)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at Greenshot.Startup.Main(String[] arguments)

Inner Exception 1:
TypeInitializationException: The type initializer for 'MS.Internal.FontCache.DWriteFactory' threw an exception.

Inner Exception 2:
InvalidCastException: Specified cast is not valid.

As that part of the code works fine without trimming and this seems to be an internal thing, it's a bit out of my influence.

Additionally I noticed that System.Windows.Forms seems to be reduced by linking, but one of the assemblies I really would like to see reduced MahApps.Metro.IconPacks.dll is not. This DLL is 14MB but I probably use around 500KB... any way to see what happened and influence this?

About the resulting size, which is already a discussion elsewhere, but I did want to mention it:
Without trimming the file was around 191MB, with current trimming it's 134MB, which is not bad.
When I use ZIP on it, it's around 42MB, so there is still room for improvement.

@Symbai
Copy link

Symbai commented Jun 5, 2019

@Lakritzator: That exception looks like a dup of dotnet/wpf#771 its probably not linker related? Fyi I agree that the size after trimming is just way too big in my opinion. A simple hello world program trimmed shouldn't be larger than 10mb.

@Lakritzator
Copy link

@Symbai
Thanks for linking the issue, it seems similar! But it seems to be triggered by the trimming, as without there is no error.
Well Greenshot is not a hello world.. 😁

For the rest: Interesting side note:
Specifying a TrimmerRootAssembly which is not referenced from a project, will crash the ILLink target with an error MSB6006 and Code -1073741819.
This is not directly what I expected.

@sbomer
Copy link
Member

sbomer commented Jun 5, 2019

@Lakritzator thanks again for reporting back! I filed a new issue about the error you get when trying to root an unreference assembly.

It's not obvious what is missing that's causing the TypeInitializationException for SystemWindows.Media.FontFamily, but in general this kind of issue is likely to come up whenever code in your app, WPF, or external packages uses reflection or native code to call into the framework. If we see that a certain class of issues is common, we may be able to improve the situation by adding common assemblies to an include list, balancing this with the size increase this would cause for simpler apps. netstandard.dll might be a candidate - I'd be curious to see what was directly referencing it in your case, and why the linker removed it. The linker has logic to deal with type forwarders, so this may also be a bug.

About MahApps.Metro.IconPacks.dll: currently dlls from external nuget packages are always rooted (not reduced). We may consider adding the option to mark packages as trimmable if it's a common request - just note that this will likely cause further breakage if that package is activated by reflection or uses reflection itself. I've filed an issue to track this at dotnet/sdk#3302.

@Lakritzator
Copy link

I'm not 100% sure, but I don'T think that I use reflection in this case. The stack trace seems to be a single dotnet stack, except for the initial startup. I will check what is referencing the netstandard, maybe it's me somewhere. But why it's removed would be hard to tell...

With 3.0.100-preview7-012267 it seems my single exe doesn't start at all, I don't get an error.
Starting from the publish directory works without issues.
I don't have the energy to check this today, it's already 23:00 (11 PM) and time for bed.
Tomorrow another day! 👍

@Lakritzator
Copy link

Lakritzator commented Jun 6, 2019

I found the issue why my application doesn't start up:
I am using System.Runtime.WindowsRuntime as a nuget package, but this is causing issues.

With 3.0.100-preview7-012282 the following issue still happens:

************** Exception Text **************
System.InvalidCastException: Specified cast is not valid.
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
   at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr)
   at MS.Internal.Text.TextInterface.Factory.Initialize(FactoryType factoryType)
   at MS.Internal.Text.TextInterface.Factory..ctor(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.Text.TextInterface.Factory.Create(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.FontCache.DWriteFactory..cctor()

Even though there were some fixes made here: dotnet/wpf#771

@dotMorten
Copy link

I'm seeing something similar to @Lakritzator

Project file:

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

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <UseWPF>true</UseWPF>
    <PublishTrimmed>true</PublishTrimmed>
    <PublishSingleFile>true</PublishSingleFile>
    <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  </PropertyGroup>

</Project>

Then publish the app to a single-exe. This works great with an empty app, But the moment you add this to your xaml, the app fails to launch. I see the same stack trace as above in EventViewer:

<TextBlock Text="Helvetica" FontFamily="Comic Sans" />

Event viewer log:

Application: ArcGISRuntime.exe
CoreCLR Version: 4.700.19.31902
.NET Core Version: 3.0.0-preview7-27820-01
Description: The process was terminated due to an unhandled exception.
Exception Info: System.TypeInitializationException: The type initializer for 'System.Windows.Media.FontFamily' threw an exception.
 ---> System.TypeInitializationException: The type initializer for 'MS.Internal.FontCache.DWriteFactory' threw an exception.
 ---> System.InvalidCastException: Specified cast is not valid.
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode, IntPtr errorInfo)
   at MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32 hr)
   at MS.Internal.Text.TextInterface.Factory.Initialize(FactoryType factoryType)
   at MS.Internal.Text.TextInterface.Factory..ctor(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.Text.TextInterface.Factory.Create(FactoryType factoryType, IFontSourceCollectionFactory fontSourceCollectionFactory, IFontSourceFactory fontSourceFactory)
   at MS.Internal.FontCache.DWriteFactory..cctor()
   --- End of inner exception stack trace ---
   at MS.Internal.FontCache.DWriteFactory.get_SystemFontCollection()
   at MS.Internal.FontCache.FamilyCollection.FromWindowsFonts(Uri folderUri)
   at System.Windows.Media.FontFamily.PreCreateDefaultFamilyCollection()
   at System.Windows.Media.FontFamily..cctor()
   --- End of inner exception stack trace ---
   at System.Windows.Media.Typeface..ctor(FontFamily fontFamily, FontStyle style, FontWeight weight, FontStretch stretch)
   at MS.Internal.Text.DynamicPropertyReader.GetTypeface(DependencyObject element)
   at MS.Internal.Text.TextProperties.InitCommon(DependencyObject target)
   at MS.Internal.Text.TextProperties..ctor(FrameworkElement target, Boolean isTypographyDefaultValue)
   at System.Windows.Controls.TextBoxView.GetLineProperties()
   at System.Windows.Controls.TextBoxView.TextCache..ctor(TextBoxView owner)
   at System.Windows.Controls.TextBoxView.EnsureCache()
   at System.Windows.Controls.TextBoxView.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.Controls.ScrollContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.ScrollViewer.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Control.MeasureOverride(Size constraint)
   at System.Windows.Controls.TextBox.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Control.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
   at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
   at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   at System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
   at System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Controls.Border.MeasureOverride(Size constraint)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Window.MeasureOverrideHelper(Size constraint)
   at System.Windows.Window.MeasureOverride(Size availableSize)
   at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   at System.Windows.UIElement.Measure(Size availableSize)
   at System.Windows.Interop.HwndSource.SetLayoutSize()
   at System.Windows.Interop.HwndSource.set_RootVisualInternal(Visual value)
   at System.Windows.Interop.HwndSource.set_RootVisual(Visual value)
   at System.Windows.Window.SourceWindowHelper.set_RootVisual(Visual value)
   at System.Windows.Window.SetRootVisual()
   at System.Windows.Window.SetRootVisualAndUpdateSTC()
   at System.Windows.Window.SetupInitialState(Double requestedTop, Double requestedLeft, Double requestedWidth, Double requestedHeight)
   at System.Windows.Window.CreateSourceWindow(Boolean duringShow)
   at System.Windows.Window.CreateSourceWindowDuringShow()
   at System.Windows.Window.SafeCreateWindowDuringShow()
   at System.Windows.Window.ShowHelper(Object booleanBox)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.DispatcherOperation.InvokeImpl()
   at System.Windows.Threading.DispatcherOperation.InvokeInSecurityContext(Object state)
   at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location where exception was thrown ---
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.ProcessQueue()
   at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
   at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
   at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
   at System.Windows.Threading.Dispatcher.Invoke(DispatcherPriority priority, Delegate method, Object arg)
   at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
   at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
   at System.Windows.Threading.Dispatcher.Run()
   at System.Windows.Application.RunDispatcher(Object ignore)
   at System.Windows.Application.RunInternal(Window window)
   at System.Windows.Application.Run(Window window)
   at System.Windows.Application.Run()
   at ArcGISRuntime.WPF.Viewer.App.Main()

@rladuca
Copy link
Member

rladuca commented Jul 2, 2019

DirectWriteForwarder is a C++/CLI DLL compiled as clr:pure. I am not sure if that has any influence on the ILLinker and what trimming it does, but this does seem very specific to single exe publishing + trimming.

@sbomer Is there anything WPF can give you to help fix this?
cc: @vatsan-madhavan

@vatsan-madhavan
Copy link
Member

Looking through the exception stack, this stands out:

StackTraceString: <none>
HResult: 80131534
0:000> !PrintException /d 000001e927b4ce58
Exception object: 000001e927b4ce58
Exception type:   System.InvalidCastException
Message:          Specified cast is not valid.
InnerException:   <none>
StackTrace (generated):
    SP               IP               Function
    00000098C2F76910 00007FFEE8641D8C System_Private_CoreLib!System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32, IntPtr)+0x1c
    00000098C2F76940 00007FFE8A9F5258 DirectWriteForwarder!MS.Internal.Text.TextInterface.Native.Util.ConvertHresultToException(Int32)+0x108
    00000098C2F769B0 00007FFE8A9F501B DirectWriteForwarder!MS.Internal.Text.TextInterface.Factory.Initialize(MS.Internal.Text.TextInterface.FactoryType)+0xdb
    00000098C2F76A80 00007FFE8A9F4D06 DirectWriteForwarder!MS.Internal.Text.TextInterface.Factory..ctor(MS.Internal.Text.TextInterface.FactoryType, MS.Internal.Text.TextInterface.IFontSourceCollectionFactory, MS.Internal.Text.TextInterface.IFontSourceFactory)+0x56
    00000098C2F76B60 00007FFE8A9F4C92 DirectWriteForwarder!MS.Internal.Text.TextInterface.Factory.Create(MS.Internal.Text.TextInterface.FactoryType, MS.Internal.Text.TextInterface.IFontSourceCollectionFactory, MS.Internal.Text.TextInterface.IFontSourceFactory)+0x42
    00000098C2F76BA0 00007FFE8A9F4B5B PresentationCore!MS.Internal.FontCache.DWriteFactory..cctor()+0xab

StackTraceString: <none>
HResult: 80004002

This is just a guess - I suspect that illink could be tripping on a compiler bug. The C++/CLI compiler emits a few bad type-refs into DirectWriteForwarder.

For e.g., it points System.Runtime.InteropServices.Marshal to System.Runtime.dll instead of System.Runtime.InteropServices.dll. There are several other examples at dotnet/wpf#634.

@vatsan-madhavan
Copy link
Member

/cc @tgani-msft

@jkoritzinsky
Copy link
Member

jkoritzinsky commented Jul 12, 2019

This issue is a duplicate of #651

@sbomer

@sbomer
Copy link
Member

sbomer commented Jul 15, 2019

Thanks @jkoritzinsky. Closing this because it has a few separate issues, some of which are fixed. Tracking the System.Windows.Media.FontFamily TypeInitializationException in #651.

@sbomer sbomer closed this as completed Jul 15, 2019
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

No branches or pull requests

8 participants