.NetCore 3 单文件发布详解

.NetCore可以将发布时产生的所有零碎文件直接打包成一个单独的运行文件相信大家都已经知道了,但在发布过程还有一些小技巧,我们今天就来聊一聊。

1. 入门

我们可以通过命令行将项目发布为单个文件:

dotnet publish -c Release -r win10-x64 -o release/win10-x64 /p:PublishSingleFile=true /p:PublishTrimmed=true

也可以通过在项目配置文件中的参数来实现:

<PropertyGroup>
    <PublishSingleFile>true</PublishSingleFile>
    <PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>    
  • 命令行参数说明
参数说明备注
--no-self-contained 不包含runtime 用户需自己安装runtime
-r 目标平台 win-x64, osx-x64, linux-x64 RID参考
-c 发布类型 Debug, Release
-o 程序发布目录 -
PublishSingleFile 发布为单个文件 true, false
PublishTrimmed 去除未引用对象 true false


PublishTrimmed参数可以有效减少发布文件的体积
--no-self-contained可减少约30M的程序体积,但不能与PublishTrimmed参数同时使用

2. 进阶

单文件非常轻松的就发布出来了,但还没过30秒,一般都会发出类似这样的嚎叫:"我去,怎么启动失败?文件加载不了?"

大多数情况是因为非程序文件没有被一起发布,别急,我们继续聊....

2.1 修改元数据

我们可以显式的排除一些文件被打包,通过为项目配置文件添加参数

<ExcludeFromSingleFile>true</ExcludeFromSingleFile>

例如,要将某些文件放在发布目录中,但不将它们捆绑到单文件中:

<ItemGroup>
    <Content Update="*.xml">
      <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </Content>
  </ItemGroup>

或者像这样复制整个目录

<ItemGroup>
    <None Update="Assets\lang\*">
      <Link>lang\%(Filename)%(Extension)</Link>
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      <ExcludeFromSingleFile>true</ExcludeFromSingleFile>
    </None>
  </ItemGroup>

2.2 修改代码

但仅这样是不够的,因为单文件是在沙箱中运行,所以需要在修改一下代码让它从程序所在目录调用文件,比如这样

#if DEBUG
  //debug模式调用路径
  string filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "config.json");
#else
  //release调用路径
  string filePath = Path.Combine(Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName), "config.json");
#endif
LoadFile(filePath)

这样就能取到原来的文件了,不过既然都说到这了,我们就顺便说说.NetCore调用目录函数之间的区别

2.3 目录区别

复制代码
//模块启动位置(非单文件模式时主程序调用为dotnet所在位置)
Console.WriteLine("StartDir:" + Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName));

//程序启动位置(单文件模式时是虚拟容器内位置)
Console.WriteLine("AppBaseDir:" + AppContext.BaseDirectory);
Console.WriteLine("AppBaseDir:" + AppDomain.CurrentDomain.SetupInformation.ApplicationBase);
Console.WriteLine("AppBaseDir:" + AppDomain.CurrentDomain.BaseDirectory);

 //程序当前目录,单文件模式时是用户目录,VSCode运行时为项目目录(不推荐使用)
Console.WriteLine("CurrentDirectory:" + Environment.CurrentDirectory);
//同上
Console.WriteLine(Directory.GetCurrentDirectory());

//程序所在的硬盘根目录
Console.WriteLine("RootDir:" + Directory.GetDirectoryRoot(
Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory)
));

//用户目录(~/)
Console.WriteLine("UserProfile:"+Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));

//桌面目录(~/Desktop) 
Console.WriteLine("DesktopDirectory:"+Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));

//系统目录(/System)
Console.WriteLine("SystemDirectory:"+Environment.SystemDirectory);

//程序数据目录(~/.config)
Console.WriteLine("ApplicationData:"+Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData));
复制代码
2.4 符号文件(可选)

默认情况下,符号文件不会嵌入到单文件中,而是作为单独的文件保留在发布目录中(如 .pdb .ni.pdb app .guid.map),设置以下属性可将符号文件包含在单文件中。


<PropertyGroup>
    <IncludeSymbolsInSingleFile>true</IncludeSymbolsInSingleFile>
</PropertyGroup>

 

本文作者:iHey

本文链接:https://www.cnblogs.com/iHey/p/13273382.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   iHey  阅读(1446)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.