本机动态库嵌入为资源文件示例; Example of native library embed as resource;
应该有更简单的方法,但还没有深入探究;
.net增加aot发布后,第三方包引用的已编译本机库不会嵌入到可执行文件中,导致发布后需要分发多个文件,此示例演示一种将本机库嵌入可执行文件作为资源的办法;
在 csproj 中添加嵌入资源的操作,示例为 sqlite 本机库
<!-- 仅当启用 aot 发布,且编译条件为 Release ,且指定运行时时进行嵌入 -->
<ItemGroupCondition="'$(PublishAot)' == 'true' and '$(Configuration)' == 'Release' and '$(RuntimeIdentifier)' != ''">
<!-- 嵌入 obj/embed_depends_files 目录下的所有文件 -->
<EmbeddedResourceInclude="$(IntermediateOutputPath)embed_depends_files\**\*"Link="\%(RecursiveDir)%(FileName)%(Extension)">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<!-- 仅当启用 aot 发布,且编译条件为 Release ,且指定运行时时在构建中复制目标文件到 obj 目录下 -->
<TargetName="__CopyEmbedDependsFilesToIntermediateOutput"AfterTargets="CopyFilesToOutputDirectory"Condition="'$(PublishAot)' == 'true' and '$(Configuration)' == 'Release' and '$(RuntimeIdentifier)' != ''">
<ItemGroup>
<!-- 复制输出目录的 e_sqlite3.* 和 libe_sqlite3.* 等文件,此值需要确认要嵌入的库可能的名称(windows、linux等不同的系统名称不同) -->
<EmbedDependsFilesInclude="$(OutputPath)e_sqlite3.*;$(OutputPath)libe_sqlite3.*" />
</ItemGroup>
<!-- 复制文件到 obj/embed_depends_files 目录下 -->
<CopySourceFiles="@(EmbedDependsFiles)"DestinationFolder="$(IntermediateOutputPath)embed_depends_files\"SkipUnchangedFiles="true" />
</Target>在 AssemblyLoadContext.Default.ResolvingUnmanagedDl 中将嵌入的资源文件复制到物理路径,然后进行加载,示例为 sqlite 本机库
AssemblyLoadContext.Default.ResolvingUnmanagedDll+=(Assembly_,stringlibraryName)=>{//当库名称不为 e_sqlite3 时不进行处理if(!libraryName.Equals("e_sqlite3")){returndefault;}varassembly=Assembly.GetExecutingAssembly();//获取 sqlite 本机库的嵌入资源名称varresourceName=assembly.GetManifestResourceNames().Single(str =>str.Contains("e_sqlite3"));//读取资源usingvarstream=assembly.GetManifestResourceStream(resourceName);if(streamisnull){returndefault;}//构造临时路径varsqliteLibraryPath=Path.Combine(Path.GetTempPath(),Path.GetFileName(resourceName));if(!File.Exists(sqliteLibraryPath)){//将本机库复制到临时路径usingvarfile=File.OpenWrite(sqliteLibraryPath);stream.CopyTo(file);}//进行加载returnNativeLibrary.Load(sqliteLibraryPath);};示例:
dotnet build -c Release -r win-x64 --no-incremental
dotnet build -c Release -r win-x64 --no-incremental
dotnet publish -c Release -r win-x64