設置一個小目標
改造前
改造后
獨立部署SCD模式,是指在使用dotnet publish 命令時帶上-r 參數運行時標識符(RID)。
目標提出原因:SCD模式下文件太亂了,很多文件在開發時大多又涉及不到,發布后如果能把文件放在一個文件夾,把自己編寫的項目的文件放在根目錄,就顯得簡略多了。沒發現改造后的文件結構看着舒服多么。
1、准備項目,並使用SCD模式發布文
mkdir apphost cd apphost dotnet new mvc dotnet build dotnet 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