Fody / Costura

Embed references as resources

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Having trouble loading native assemblies. Given instructions not working

DerKO9 opened this issue · comments

commented

ONLY active OSS contributors OR people who buy me a coffee can ask questions here. If you don't do either of these things - DO NOT FILE HERE OR I WILL SIMPLY REMOVE YOUR ACCOUNT :)

Give as much details as humanly possible if you want any sort of answer!

Enter Question Below (don't delete this line)

Proof of contribution: https://opencollective.com/derko

Hi I am having trouble with native assemblies. I have made a very simple .Net Framework 4.6.1 console application to showcase my issue and is located here https://github.com/DerKO9/CosturaTest

I want to use nuget package "Grcp.Core", but this package use a native assembly called "grpc_csharp_ext" either .x86 or .x64.
I have followed instructions online and added this to my Fody.Weavers.xml
CosturaFodyXML

I have added the "grpc_csharp_ext" assemblies to Costura32 and Costura64 folders and have changed them to "Embedded Resource"
CosturaEmbeddedResource

I use dnSpy, a .NET assembly editor, to confirm that both "grpc_csharp_ext" assemblies are included in the final executable in the Resources folder.
CosturaDnspy

This doesn't work, however, and I keep getting a System.IO.FileNotFoundException in my Program.cs
CosturaFail

If you are cloning/running my repo, one thing to note: I have a post build event
Copy "$(ProjectDir)\bin\Debug\CosturaTest.exe" "$(ProjectDir)\bin\IsolationTest"
Which moves the built EXE into a separate folder called "IsolationTest" so that I can test it actually running on its own away from the "grpc_csharp_ext" assemblies.
I then set it to run the isolated EXE
CosturaDebugPath

I have already tried

  • Setting LoadAtModuleInit='false' and using CosturaUtility.Initialize();
  • Using <PreloadOrder></PreloadOrder> instead of <Unmanaged32Assemblies></Unmanaged32Assemblies>

image

What version of VS are you using?

btw: consider doing yourself a favor and use the modern project sdk instead of this horrible old csproj format.

The only thing I changed was adding this line so Fody would not complain:

    <MsBuildMajorVersion>16.0</MsBuildMajorVersion>
commented

Thanks for the reply!

I am using the latest version of VS 2019 and my project is .Net Framework 4.6.1.

Will this only work in .Net Core? I have just made the same simple console app but with .Net Core 3.1 instead of .Net Framework and it all worked perfectly. Unfortunately I am making an add-on for a .Net Framework 4.6.1 program and I must use .Net 4.6.1 for my add-on to be compatible. Should I be using an older version of Fody and Costura for all this to work?

Just to confirm, you were running the EXE in its own separate directory away from "grpc_csharp_ext.x86.dll"?

This line
<MsBuildMajorVersion>16.0</MsBuildMajorVersion>
where did you add this? Is this something that will help me?

I am using the latest version of VS 2019 and my project is .Net Framework 4.6.1.

You can use the modern project SDK even on older .NET projects.

Just to confirm, you were running the EXE in its own separate directory away from "grpc_csharp_ext.x86.dll"?

No, I cloned your project and ran it successfully using the attached debugger. Will try to run it separately as well.

Did some quick research, it's because grpc force loads the native assemblies from the app directory:

https://github.com/grpc/grpc/blob/e5562a66a4e6bd1900bc9b144587d6d593720c1d/src/csharp/Grpc.Core/Internal/NativeExtension.cs#L87

The only thing I can recommend is to manually extract the files (the resource names can be viewed via ILSpy) manually to the directory. Note though that this requires write access to the executing assembly directory.

commented

You can use the modern project SDK even on older .NET projects.

Huh, I will look into the modern project SDK and try to add that to my code.

Did some quick research, it's because grpc force loads the native assemblies from the app directory:
The only thing I can recommend is to manually extract the files (the resource names can be viewed via ILSpy) manually to the directory

Wow I would have never figured that one out.

I looked up online how to manually extract the files, copy pasted example code, and came up with this
CosturaExtract

Everything in the red box is new code which does the extraction. I had to add a filename.Replace("costura32.", "") so that the "costura32.grpc_csharp_ext.x86.dll" becomes "grpc_csharp_ext.x86.dll"

Now I just got to clean this up, add logic to differentiate x86 and x64, and I think I will have a working solution.

Being able to give my users just a single .dll file will be SOOOO nice. Thank you so much for helping me!

Glad you figured it out 👍

add logic to differentiate x86 and x64

I believe Costura does this by checking the length / size of a long.