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

ILMerge fails to properly merge WpfMath #202

Closed
davidagross opened this issue Sep 5, 2019 · 9 comments
Closed

ILMerge fails to properly merge WpfMath #202

davidagross opened this issue Sep 5, 2019 · 9 comments

Comments

@davidagross
Copy link

Repository https://github.com/davidagross/ILMerge-vs-WpfMath provides a MWE of this error.

Basically, when WpfMath.dll isn't next to the merged, standalone executable, the render fails:

System.TypeInitializationException: The type initializer for 'WpfMath.DefaultTexFont' threw an exception. ---> System.IO.FileNotFoundException: The system cannot find the file specified. (Exception from HRESULT: 0x80070002)
   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   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.CreateFontFace(Uri filePathUri, UInt32 faceIndex, FontSimulations fontSimulationFlags)
   at System.Windows.Media.GlyphTypeface.Initialize(Uri typefaceSource, StyleSimulations styleSimulations)
   at WpfMath.DefaultTexFontParser.CreateFont(String name)
   at WpfMath.DefaultTexFontParser.GetFontDescriptions()
   at WpfMath.DefaultTexFont..cctor()
   --- End of inner exception stack trace ---
   at WpfMath.DefaultTexFont..ctor(Double size)
   at WpfMath.TexFormula.GetRenderer(TexStyle style, Double scale, String systemTextFontName)
   at WpfMath.Extensions.RenderToPng(TexFormula texForm, Double scale, Double x, Double y, String systemTextFontName)
   at ILMerge_vs_WpfMath.Renderer.DisplayEquation()
   at ILMerge_vs_WpfMath.Renderer..ctor()

indicating that the merge was not successfull. This is also tracked in dotnet/ILMerge#70.

@ForNeVeR
Copy link
Owner

ForNeVeR commented Sep 6, 2019

The code you mentioned most likely fails because of resource usage, see this line: https://github.com/ForNeVeR/wpf-math/blob/a09779dfbec9a4be1b8ed4df312a60255ac697d0/src/WpfMath/DefaultTexFontParser.cs#L224

Are you aware how ILMerge behaves with regarding to resources? Should we make any adjustments to the code to be ILMerge-compatible?

@davidagross
Copy link
Author

I'm not aware, and I'm also personally unfamiliar with Pack URIs.

Here is what WpfMath.dll

image

and my Renderer.dll

image

look like in ILSpy. It's not obvious to me that the resources that are being looked for are changing relative paths, but it does seems obvious that this is near the root of the problem. Any thoughts?

@davidagross
Copy link
Author

@ForNeVeR, I'm looking at this again and found someone else dealing with this kind of issue in another merger. However, it seems like their issue was with the path to the resource being based on the assembly name, which it doesn't look like is the cases here.

Do you see any issues above with the paths to the resources and why or how the path might change depending on the application? If not, then I think there's an issue on the merging side, but if so, then maybe there is a way to make the URI in this repo more robust to merging. Thoughts? Thanks!

@ForNeVeR
Copy link
Owner

ForNeVeR commented Nov 9, 2019

Okay, it's totally possible that the assembly name should be right in our code (i.e. we should take the current assembly name instead of the hard-coded WpfMath). Could you please try it? Replace "WpfMath" in this line with a variation of System.Reflection.Assembly.GetExecutingAssembly.GetName().Name, and then run your merger and tests again.

davidagross pushed a commit to davidagross/wpf-math that referenced this issue Nov 12, 2019
Change based on conversation in ForNeVeR#202, basic attempt failed
@davidagross
Copy link
Author

I get the kind of change you're interested in making, but I lack the pack URI experience and time at this very moment to dive more deeply into this other than the iteration in davidagross@42afb17. When that gets built and referenced in my test project I actually get the following error before deleting the collocated DLL, meaning I've regressed the code and would appreciate any tips on what I'm looking for in terms of variations on the gotten assembly name.

I have my test project all set up to test updates to this library and I'm happy to continue the work with a bit more of your guidance and support, but I'm also happy to hand off the assignment of this issue to you if you want to take it from here. Thanks, and thanks for resolving to work on this given the state of affairs explained in dotnet/ILMerge#70.

image

@ForNeVeR ForNeVeR assigned ForNeVeR and unassigned davidagross Nov 13, 2019
@ForNeVeR
Copy link
Owner

Ok, now it is the moment when I'll need to take a closer look at the project. Seems like you've done everything right.

@davidagross
Copy link
Author

Happy New Year, @ForNeVeR. Any progress on this, or anything I can help test on my end?

@ForNeVeR
Copy link
Owner

ForNeVeR commented Jan 3, 2020

Unfortunately, not yet; sorry for the pause.

I'll try to make it till 2020-01-09.

@ForNeVeR
Copy link
Owner

I've taken a look at the issue. The following patch doesn't solve the problem, even if it was supposed to:

Index: src/WpfMath/DefaultTexFontParser.cs
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/WpfMath/DefaultTexFontParser.cs	(revision 7ae7168a86dcd425a238ee25a9c9e2e72d21d1ec)
+++ src/WpfMath/DefaultTexFontParser.cs	(date 1584174774150)
@@ -221,7 +221,8 @@
         private GlyphTypeface CreateFont(string name)
         {
             // Load font from embedded resource.
-            var fontUri = new Uri(string.Format("pack://application:,,,/WpfMath;component/{0}{1}", fontsDirectory, name));
+            var assemblyShortName = Assembly.GetExecutingAssembly().GetName().Name;
+            var fontUri = new Uri($"pack://application:,,,/{assemblyShortName};component/{fontsDirectory}{name}");
             return new GlyphTypeface(fontUri);
         }

Even when I'm trying to use a correct assembly name (according to the pack URIs documentation), the following exception gets thrown (note it's not "file not found" anymore, but something about "I/O Error occurred"):

There was an error:System.TypeInitializationException: The type initializer for 'WpfMath.DefaultTexFont' threw an exception. ---> System.IO.IOException: I/O error occurred.

   at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
   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.CreateFontFace(Uri filePathUri, UInt32 faceIndex, FontSimulations fontSimulationFlags)
   at System.Windows.Media.GlyphTypeface.Initialize(Uri typefaceSource, StyleSimulations styleSimulations)
   at System.Windows.Media.GlyphTypeface..ctor(Uri typefaceSource)
   at WpfMath.DefaultTexFontParser.CreateFont(String name) in D:\X-Files\Projects\wpf-math\src\WpfMath\DefaultTexFontParser.cs:line 226
   at WpfMath.DefaultTexFontParser.GetFontDescriptions() in D:\X-Files\Projects\wpf-math\src\WpfMath\DefaultTexFontParser.cs:line 74
   at WpfMath.DefaultTexFont..cctor() in D:\X-Files\Projects\wpf-math\src\SharedMath\DefaultTexFont.cs:line 26
   --- End of inner exception stack trace ---
   at WpfMath.DefaultTexFont..ctor(Double size)
   at WpfMath.TexFormula.GetRenderer(TexStyle style, Double scale, String systemTextFontName) in D:\X-Files\Projects\wpf-math\src\WpfMath\TexFormula.cs:line 27
   at WpfMath.Extensions.RenderToPng(TexFormula texForm, Double scale, Double x, Double y, String systemTextFontName) in D:\X-Files\Projects\wpf-math\src\WpfMath\Extensions.cs:line 14
   at ILMerge_vs_WpfMath.Renderer.DisplayEquation() in T:\Temp\ILMerge-vs-WpfMath\ILMerge-vs-WpfMath\ILMerge-vs-WpfMath\Renderer.cs:line 43
   at ILMerge_vs_WpfMath.Renderer..ctor() in T:\Temp\ILMerge-vs-WpfMath\ILMerge-vs-WpfMath\ILMerge-vs-WpfMath\Renderer.cs:line 27

Here's the resource section of the binary after ILMerge:
Resource section as shown by Rider decompiler

It looks like WpfMath.g.resources should be renamed to ILMerge-vs-WpfMath.Standalone.g.resources or something like that, but I haven't tried that.

From this investigation, it's clear that we cannot do anything about the issue in the WPF-Math code currently.

If you'll ever found a way to rename the resource using ILMerge, then please inform me, and I'll try if the patch helps the resulting application to work. If it is, then we'll merge it.

I'll not merge that patch to the main code base for now, because we've no proof that it'll work even after some resource-related workarounds with ILMerge.

For now, I'll close the issue as (supposedly) non-actional from our side. Feel free to comment though, if it becomes actionable then I'll gladly reopen and fix it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants