使用 exe 编译非托管 DLL
Compiling unmanaged DLLs with exe
我正在尝试使用 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 的 "Build Action" 更改为 "Embedded Resource",虽然可执行文件的大小显着增加,但如果我在没有 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。
将文件添加到您的项目中 "Embedded resource":
然后保存到主程序集目录:
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 无法加载到域中,您只需要将其保存在应用程序根目录中。
我找到了解决办法!
显然我需要做的就是在项目的根目录中创建文件夹 Costura32 和 Costura64,将 32 位和 64 位 DLL 放入它们各自的文件夹中,将它们的构建操作更改为 "Embedded Resource" 并使用我原来的 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>
我正在尝试使用 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 的 "Build Action" 更改为 "Embedded Resource",虽然可执行文件的大小显着增加,但如果我在没有 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。
将文件添加到您的项目中 "Embedded resource":
然后保存到主程序集目录:
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 无法加载到域中,您只需要将其保存在应用程序根目录中。
我找到了解决办法!
显然我需要做的就是在项目的根目录中创建文件夹 Costura32 和 Costura64,将 32 位和 64 位 DLL 放入它们各自的文件夹中,将它们的构建操作更改为 "Embedded Resource" 并使用我原来的 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>