1

Problem

I have a WPF Application that is referencing Microsoft.mshtml Primary Interop Assembly. I'm creating a native image of my app using NGen. I'm afraid the native image is never being loaded if I start my app.

Reproduction Info

E.g. create new WPF Application "WpfApplication1" in Visual Studio, add reference to "C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll", set Embed Interop Types to false, set Specific Version to false and set Copy Local to true. Use some type of Microsoft.mshtml like instantiating mshtml.HTMLDocumentClass. After building the app, run NGen from "c:\Windows\Microsoft.NET\Framework\v4.0.30319" like this:

ngen install "%PATHTOMYAPPDIR%\WPFApplication1.exe" /NoDependencies

NGen does not show any errors. After having started my app, I'm verifying if the native image has been loaded by using vmmap or process explorer. Unfortunately none of them is showing the created native image.

Fusion log

So I've enabled the fusion log viewer and this is what it tells me:

* Assembly Binder Log Entry (3/13/2016 @ 11:30:48 AM) *

The operation was successful. Bind result: hr = 0x0. The operation completed successfully.

Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll Running under executable C:\Users\azureuser\Documents\visual studio 2015\Projects\WpfApplication1\WpfApplication1\bin\Release\WpfApplication1.exe
--- A detailed error log follows.

LOG: Start validating all the dependencies.
LOG: [Level 1]Start validating native image dependency mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: [Level 1]Start validating IL dependency PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
LOG: [Level 1]Start validating IL dependency WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
LOG: [Level 1]Start validating IL dependency System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: [Level 1]Start validating IL dependency PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
LOG: [Level 1]Start validating native image dependency System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: [Level 2]Start validating native image dependency mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
LOG: [Level 2]Start validating IL dependency System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
LOG: [Level 2]Start validating IL dependency System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
Native image has correct version information.
LOG: [Level 1]Start validating IL dependency UIAutomationTypes, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
LOG: [Level 1]Start validating IL dependency Microsoft.mshtml, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a.
WRN: Cannot load IL assembly. (hr = 0x80131040).
WRN: No matching native image found.
LOG: IL assembly loaded from C:\Users\azureuser\Documents\visual studio 2015\Projects\WpfApplication1\WpfApplication1\bin\Release\WpfApplication1.exe.

Remarks

  • If I remove the Microsoft.mshtml reference including the mshtml code, the native image is loaded as expected. So in general ngening works on my systems.
  • I've tested this behaviour on three different OSs producing the same result: Windows 7 Ultimate, Windows Server 2012 Datacenter and Windows 10.
  • Disabling load verification by running sn.exe -Vr *,* does not change the behaviour
  • As the Microsoft.mshtml that is actually loaded from GAC is slightly different from the one in "C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies" (different certificates), I also tried to directly reference the one in the GAC producing no different result
  • Putting the one under "C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies" into the GAC by running gacutil -if does not work either
  • I built this app using VS2013 targeting .net 4.5 and VS2015 targeting .net 4.6
tstadel
  • 31
  • 5
  • 1
    Microsoft.mshtml.dll is an ancient assembly and targets .NET 1.0, a version of .NET that did not have NGen yet. Pretty unclear what might happen, I don't want to screw up my machine. You'll have to tell Fuslogvw to log the native image binds to see more, bottom button. You should *not* be doing this, the Embed Interop Types is always superior to taking a PIA dependency. Set it back to True to trivially solve your problem. – Hans Passant Mar 13 '16 at 13:52
  • Thanks for your reply. Setting Embed Interop Types to true is not an option in my case. If I do, VS tells me: "Interop type 'mshtml.HTMLDocumentClass' cannot be embedded. Use the applicable interface instead." The fusion log you see in my post concers already the native category. – tstadel Mar 13 '16 at 14:33
  • Sure, very trivial to fix. Just follow the direction that the error message gives you and use the interface instead. Delete "Class" from the identifier name and it will work just fine. Also avoids a [very nasty failure mode](http://stackoverflow.com/a/10196040/17034), two bangs for one buck. – Hans Passant Mar 13 '16 at 14:34
  • Well, thanks for a while. Indeed, if I only use the interfaces/enums of Microsoft.mshtml in my Testapp, it works fine. But as you can imagine, I'm not doing this for fun. So I have to evaluate, if the real app I'm dealing with, needs anything more from Microsoft.mshtml.dll. – tstadel Mar 13 '16 at 14:50
  • Just do this correctly and you'll automatically have more time for fun. There is no "more", the XxxClass identifiers were a design mistake. Albeit that the intention was good, C# programmers don't like using the *new* keyword on interface types. – Hans Passant Mar 13 '16 at 14:56
  • We're using the Class types only for type comparison (e.g. obj.GetType() == mshtml.HTMLTableCellClass). If I'm using the interface now and take the C# "is" construct (e.g. obj is mshtml.HTMLTableCell), this returns true even for HTMLBodyClass objects, unfortunately. A possible Workaround for me seems to be to match the obj.GetType().FullName string. But this looks a little bit odd to me. Do you have any other suggestions for this Situation? – tstadel Mar 14 '16 at 09:46
  • Not off the bat, surely best to ask a question about it and show us exactly what you are doing. – Hans Passant Mar 14 '16 at 09:48

0 Answers0