设置一个小目标
改造前
改造后
独立部署SCD模式,是指在使用dotnet publish 命令时带上-r 参数运行时标识符(RID)。
目标提出原因:SCD模式下文件太乱了,很多文件在开发时大多又涉及不到,发布后如果能把文件放在一个文件夹,把自己编写的项目的文件放在根目录,就显得简略多了。没发现改造后的文件结构看着舒服多么。
1、准备项目,并使用SCD模式发布文
mkdir apphostcd apphostdotnet new mvcdotnet builddotnet publish -c Release -r win10-x64 -o "c:\publish"
现在我们得到了发布后的文件,现在建立runtime文件夹,并把除配置文件外的文件都移过去,
bower.json bower的配置文件
bundleconfig.json 合并css和js文件的配置文件
appsettings.json 项目运行参数文件
appsettings.Development.json 开发模式的项目运行参数文件
apphost.runtimeconfig.json coreclr的配置文件
apphost.deps.json 项目程序集引用关系文件
开始执行apphost.exe
缺少hostfxr.dll
复制此文件过来
缺少hostpolicy.dll
复制此文件过来
看不出项目的原因吧,这是需要开始Trace,在系统环境变量添加新的系统变量COREHOST_TRACE 值设置为1
再次执行后
怎么办,无路可走了,把错误命令在github上搜索上,看有结果没
https://github.com/dotnet/core-setup
下载源码,调试下程序,看问题出在哪里
这里使用2.0.0版本的源码
https://github.com/dotnet/core-setup/blob/master/Documentation/building/windows-instructions.md
准备环境
win8.1系统(硬盘至少50G,不然会不够用的)
Visual Studio 2015 Update 3
CMake
Git
PowerShell
DotNet Core SDK
以上是文档说的
但是还需要准备一个 dotnet-dev-win-x64.1.0.0-rc4-004771.zip
编译的时候,需要会提示需要这个版本的sdk,不然编译通不过
环境准备好,就可以执行build.cmd了,等着吧编译时间很长
编译完成后,可以在\Bin\obj\win-x64.Debug\corehost\cli\exe\apphost目录找到 apphost.vcxproj
用vs2015打开
并把 Bin\obj\win-x64.Debug\corehost\cli\dll\hostpolicy.vcxproj
Bin\obj\win-x64.Debug\corehost\cli\dll\hostfxr.vcxproj
加入到apphost.sln解决方案中
然后改动 hostpolicy.vcxproj和hostfxr.vcxproj的输出目录到
Bin\obj\win-x64.Debug\corehost\cli\exe\apphost\Debug
然后把上面改动发布的文件publish里的文件全部复制到
Bin\obj\win-x64.Debug\corehost\cli\exe\apphost\Debug文件
编译下项目,就可以开始调试了
我们来整理下 apphost.exe的加载逻辑
corehost.app入口在这里,可以一直F11下去,直到启动coreclr
apphost.exe 主要功能是检查文件是否合法
corehost.app main()入口
run() 检查执行路径
is_exe_enabled_for_execution() 检查是不是又dotnet build 编译的文件,dotnet build编译的时候会嵌入exe文件中一个 dll文件名的hash值,因为我们是调试生成的exe文件,所以肯定通不过hash值的检查的,所以我们把corehost.app文件的第147行的 return StatusCode::AppHostExeNotBoundFailure; 注释掉
下面就是加载 hostfxr.dll文件
源码逻辑验证了上面移动文件的错误提示信息
hostfxr.dll 读取runtimeconfig.json文件
hostfxr.cpp hostfxr_main()是入口
muxer.execute()
detect_operating_mode() libhost.app 判断执行coreclr的模式 host_mode_t 分
invalid = 0,
muxer, // Invoked as "dotnet.exe".
standalone, // Invoked as "appname.exe" from the application base: either "standalone" or "branded". When implementing branded exes, rename this to "apphost"
split_fx // Invoked as "corehost.exe" for xunit scenarios -- this has to be fixed by the CLI to not use this executable and this mode should not be supported.
// Split FX means, the host is operating like "corerun.exe" in a split location from the application base (CORE_ROOT equivalent), but it has its "hostfxr.dll"
// next to it.
执行 standalone 模式
parse_args_and_execute() fx_muxer.cpp 找到runtimeconfig文件
read_config_and_execute fx_muxer.cpp 找到并读取文件
get_runtime_config_paths_from_app libhost.app 找到文件
config() runtime_config.app 格式化文件
ensure_parsed runtime_config.app
execute_app() 执行hostpolicy.dll
hostpolicy.dll 读取deps.json文件
corehost_main hostpolicy.app 入口
deps_resolver_t() 格式化deps.json文件
load() deps_format.cpp 读取deps.json文件
resolve_probe_paths() deps_resolver.cpp
to_dir_path() deps_enty.cpp 检查文件是否存在
启动coreclr.dll
到这里就可以 找到了 to_path()方法来判断文件是否存在,修改to_dir_path()方法来实现修改如下
但是因为asp net core 使用了DI,还需要修改 Microsoft.Extensions.DependencyModel.dll不然还是会报着不到文件
最后可以找到 TryResolveAssemblyPaths() AppBaseCompilationAssemblyResolver.cs
修改如下,
经过上面的分析,发布后,只需要替换Microsoft.Extensions.DependencyModel.dll和hostpolicy.dll 两个文件就实现了目标
可调试文件源码
https://github.com/xakepbean/core-setup-debug
原文:http://www.cnblogs.com/xakep/articles/7751273.html
.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com