1
votes

I am trying to embed a bunch of DLLs in my C# executable using costura fody, but I am having some trouble with 2 DLLs. I am using the NAudio library and the NAudio.Lame library, and while both DLLs compile perfectly into the exe, the NAudio.Lame package adds the dlls "libmp3lame.64.dll" and "libmp3lame.32.dll", which I am not able to compile with the exe. I have tried adding the following in the FodyWeavers.xml file under the Costura node:

<Unmanaged32Assemblies>
    libmp3lame.32
</Unmanaged32Assemblies>
<Unmanaged64Assemblies>
    libmp3lame.64
</Unmanaged64Assemblies>

The XML does not change the filesize of the exe, so I assume it did nothing.

I have also tried to change the "Build Action" of the DLLs to "Embedded Resource", and while the executable file size increases significantly, I get a Runtime DLLNotFoundExeption if I launch the program without the DLLs in the same folder as the exe.

EDIT: I now noticed that I only need the 64 bit dll for the program to run on my computer, but I am not able to add only that dll either

EDIT2: I tried setting up an event for AssemblyResolve using the following code:

    private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) {
        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Client.libmp3lame.64.dll")) {
            byte[] assemblyData = new byte[stream.Length];
            stream.Read(assemblyData, 0, assemblyData.Length);
            return Assembly.Load(assemblyData);
        }
    }

It left a System.BadImageFormatException this time, as I think this code only works for managed DLLs.

2

2 Answers

4
votes

I found a solution!

Apparently all I needed to do was to create the folders Costura32 and Costura64 in the root of my project, put the 32-bit and 64-bit DLLs in their respective folders, change their build action to "Embedded Resource" and compile with my original Costura settings.

This is how my project looks:

Screenshot ofsolution explorer

This is my FodyWeavers.xml:

<?xml version="1.0" encoding="utf-8"?>
<Weavers>
  <Costura>
    <IncludeAssemblies>
        NAudio
        NAudio.Lame
    </IncludeAssemblies>
    <Unmanaged32Assemblies>
      libmp3lame.32
    </Unmanaged32Assemblies>
    <Unmanaged64Assemblies>
      libmp3lame.64
    </Unmanaged64Assemblies>  
  </Costura>
</Weavers>
1
votes

Add the file to your project as "Embedded resource":

Embedded resource

Save then to the main assembly directory:

Assembly assembly = this.GetType().Assembly;
string assemblyLocation = System.IO.Path.GetDirectoryName(assembly.Location);

if (!System.IO.File.Exists(System.IO.Path.Combine(assemblyLocation, "libmp3lame.64.dll")))
{
    using (FileStream fileStream = new FileStream(assemblyLocation + "libmp3lame.64.dll", FileMode.CreateNew, FileAccess.Write, FileShare.None))
        assembly.GetManifestResourceStream("Client.libmp3lame.64.dll").CopyTo(fileStream);
}

COM dll cannot be loaded to the domain, you need to save it on application root only.