【问题标题】:Compiling unmanaged DLLs with exe使用 exe 编译非托管 DLL
【发布时间】:2019-02-15 17:35:54
【问题描述】:

我正在尝试使用 costura fody 在我的 C# 可执行文件中嵌入一堆 DLL,但是我在使用 2 个 DLL 时遇到了一些问题。我正在使用 NAudio 库和 NAudio.Lame 库,虽然两个 DLL 都可以完美地编译到 exe 中,但 NAudio.Lame 包添加了 dll“libmp3lame.64.dll”和“libmp3lame.32.dll”,我就是无法用exe编译。我尝试在 Costura 节点下的 FodyWeavers.xml 文件中添加以下内容:

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

XML 不会改变 exe 的文件大小,所以我认为它什么也没做。

我还尝试将 DLL 的“构建操作”更改为“嵌入式资源”,虽然可执行文件的大小显着增加,但如果我在相同的文件夹中启动没有 DLL 的程序,我会得到一个运行时 DLLNotFoundExeption exe。

编辑:我现在注意到我只需要 64 位 dll 就可以让程序在我的计算机上运行,​​但我也不能只添加那个 dll

EDIT2:我尝试使用以下代码为 AssemblyResolve 设置事件:

    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);
        }
    }

这次它留下了 System.BadImageFormatException,因为我认为此代码仅适用于托管 DLL。

【问题讨论】:

    标签: c# .net compilation fody-costura


    【解决方案1】:

    我找到了解决办法!

    显然,我需要做的就是在我的项目的根目录中创建文件夹 Costura32 和 Costura64,将 32 位和 64 位 DLL 放在各自的文件夹中,将它们的构建操作更改为“嵌入式资源”并编译使用我原来的 Costura 设置。

    这就是我的项目的样子:

    这是我的 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>
    

    【讨论】:

      【解决方案2】:

      将该文件作为“嵌入式资源”添加到您的项目中:

      然后保存到主程序集目录:

      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 无法加载到域中,您只需将其保存在应用程序根目录下即可。

      【讨论】:

      • 你说的主程序集目录,是不是我在Program.cs的Main函数中添加了代码?
      • 您需要在访问此程序集之前运行此代码,因此您可以将其添加到 Program.cs 中的 Main 函数中或在使用 NAudio 之前。 (例如:NAudio.Initialize)
      • 我确实得到了它的一些小改动,但是它将 dll 添加到 EXE 的目录中。是否有直接从资源加载 DLL 的更简洁的解决方案?
      • 没办法。您需要 EXE 目录上的 dll 来使用它。
      • 显然 Costura 将您的 dll 注册到系统程序集缓存。
      猜你喜欢
      • 2013-07-30
      • 2010-10-18
      • 1970-01-01
      • 2021-07-27
      • 1970-01-01
      • 2017-03-07
      • 1970-01-01
      • 1970-01-01
      • 2010-10-14
      相关资源
      最近更新 更多