FEATURED · 精选文章

使用本地构建的 apphost 与 .NET 根目录进行运行时开发调试

发布时间 / 2026/9/20 20:58:10
来源 / 创域科博编辑部
栏目 / 资讯中心
使用本地构建的 apphost 与 .NET 根目录进行运行时开发调试 语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载导读在 .NET 运行时仓库dotnet/runtime中开发、调试宿主hosting组件时默认的构建流程会通过 NuGet 拉取与当前 SDK 匹配的Microsoft.NETCore.App.Host包来生成应用程序的可执行文件apphost。当你在本地修改了宿主源码、希望用刚构建出来的二进制验证效果时就需要绕过这一默认机制。本文基于仓库文档 docs/workflow/testing/host/using-apphost.md系统讲解两种核心方法通过 MSBuild 属性AppHostSourcePath/SingleFileHostSourcePath让 SDK 使用本地构建的宿主以及通过DOTNET_ROOT环境变量让框架依赖应用指向本地 .NET 布局。读完本文你将能在不修改 SDK、不重装运行时的情况下直接用本地产物运行和调试应用。一、背景SDK 是如何选择 apphost 的1.1 什么是 apphost在 .NET 的宿主组件体系中apphost是应用的入口宿主entry-point host之一。docs/design/features/host-components.md 将 .NET Core 的默认宿主拆分为以下几类dotnet可执行文件来自共享位置通常是机器上最新版本常被称为 muxerapphost可执行文件让应用拥有真正可直接运行的可执行文件可执行文件以应用名命名comhost动态库用于 COM 服务器宿主ijwhost动态库用于加载 IJW 程序集nethost动态库供非 .NET 原生应用动态加载 .NET Core 代码。入口宿主只做一件事找到hostfxr库并把控制权交给它。其中apphost查找hostfxr的顺序是先查应用所在目录对apphost而言即其内嵌的应用路径再查DOTNET_ROOT环境变量指定的路径最后查默认共享位置。1.2 SDK 的默认查找逻辑当你执行dotnet build/dotnet publish时SDK 会为应用生成一个以应用名命名的可执行文件即apphost它会被重命名为与应用同名被更新为与应用的托管.dll关联即把托管 DLL 名称写入可执行映像中。SDK 查找apphost的机制是在dotnet_root/packs下寻找已安装的、与当前操作系统、架构、版本匹配的Microsoft.NETCore.App.Host包若找不到匹配项则下载对应的 NuGet 包。相关逻辑在 dotnet/sdk 仓库的src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Sdk.FrameworkReferenceResolution.targets中。注意本仓库是只读的 dotnet/runtime 源码仓库不含 SDK 源码上述 SDK 行为属于官方文档与 SDK 目标文件明确描述的既定事实。二、方法一用AppHostSourcePath指定本地 apphost2.1 属性说明要让 SDK 在构建项目时使用你指定的本地apphost请在项目文件中设置AppHostSourcePath属性其值为本地apphost二进制的完整路径。以本仓库为例构建宿主后二进制通常位于repo_root/artifacts/bin/os-arch.configuration/corehost/apphost[.exe]其中os为操作系统如linux、win、osxarch为架构如x64、arm64configuration为构建配置Debug/ReleaseWindows 上带有.exe后缀。示例配置PropertyGroup AppHostSourcePath[full_path_to_apphost]/AppHostSourcePath /PropertyGroup设置之后构建与发布你的项目时SDK 将直接使用该二进制作为应用的可执行文件而不再从 packs 目录或 NuGet 中寻找宿主。2.2 源码佐证apphost 如何绑定托管 DLL为什么 SDK 更新 后的apphost就能知道自己该运行哪个托管 DLL这与apphost二进制内部的一个占位哈希机制有关。在 src/native/corehost/apphost/apphost.c 中可以看到编译产物内嵌了一个固定的占位字符串EMBED_HASH_FULL_UTF8即foobar的 SHA-256 值c3ab8ff13720e8ad9047dd39466b3c89 74e592c2fa383d4a3960714caef0c4f2dotnet build会把这个占位符替换为应用的托管 DLL 文件名可带相对路径相对 apphost 可执行文件所在目录运行时is_exe_enabled_for_execution会读取该内嵌值若仍是占位哈希则报错 This executable is not bound to a managed DLL to execute.若值有效则将其解析为托管 DLL 路径继续执行该内嵌字符串为 NUL 结尾的 UTF-8最大长度为 1024 字节不含 NUL。这一设计解释了AppHostSourcePath的用途你提供的是一个未绑定的原始apphost模板SDK 拿到它之后再写入绑定应用 DLL 名。因此本地构建产物直接可用作该属性值。2.3 构建宿主二进制要让artifacts/bin/.../corehost/apphost存在需要先构建宿主子集。宿主测试文档 docs/workflow/testing/host/testing.md 给出了命令build.sh -subset host -runtimeConfiguration Release -librariesConfiguration ReleaseWindows 上为build.cmd。host子集默认包含host.native原生宿主二进制与host.tests宿主测试等组成部分。三、方法二SingleFileHostSourcePath指定单文件宿主对于发布为单文件single-file的应用SDK 使用singlefilehost二进制作为宿主。若想使用本地构建的singlefilehost需要同时设置两个属性PropertyGroup PublishSingleFiletrue/PublishSingleFile SingleFileHostSourcePath[full_path_to_singlefilehost]/SingleFileHostSourcePath /PropertyGroup其中SingleFileHostSourcePath指向本地singlefilehost二进制的完整路径例如repo_root/artifacts/bin/os-arch.configuration/corehost/singlefilehost[.exe]从仓库目录结构看src/native/corehost/apphost 下同时存在apphost.c普通宿主与static/singlefilehost.def、static/singlefilehost_unixexports.src、static/singlefilehost_freebsdexports.src单文件宿主相关源文件与导出定义可以推断两者由同一目录下的构建脚本分别产出到corehost目录文件名分别为apphost与singlefilehost。设置完成后dotnet publish -r rid /p:PublishSingleFiletrue生成的可执行文件将基于你指定的本地singlefilehost。四、方法三替代方案速览原文档还提到除了上述 MSBuild 属性还有两类替代途径复制到 packs / NuGet 缓存把目标 apphost 复制到dotnet_root/packs下对应版本目录以及对应的 NuGet 缓存目录使 SDK 默认查找逻辑命中本地打包 NuGet 包本地构建Microsoft.NETCore.App.HostNuGet 包并通过NuGet.config与KnownAppHostPackitem 配置应用使用它们。这两种方式适合需要模拟发布物完整落盘的场景如测试安装布局但操作链路更长日常迭代调试推荐直接使用AppHostSourcePath。五、方法四用DOTNET_ROOT指向本地 .NET 布局5.1 适用场景与原理对于框架依赖型应用framework-dependent application可执行文件运行时会从共享位置解析 .NET 运行时与框架。若你希望应用直接使用本地构建的运行时、宿主与库可以设置DOTNET_ROOT环境变量指向本地 .NET 布局。其底层原理在宿主源码中清晰可见。宿主查找 dotnet 根目录的次序见 src/native/corehost/hostmisc/utils.c 的utils_get_dotnet_root_from_env先查架构特定变量DOTNET_ROOT_ARCH例如DOTNET_ROOT_X64定义见 src/native/corehost/hostmisc/utils.h在 Windows WOW64 进程下查DOTNET_ROOT(x86)最后查通用变量DOTNET_ROOT。fxr_resolver.c中fxr_resolver_t的搜索位置枚举src/native/corehost/fxr_resolver.h也明确包含fxr_search_location_environment_variable即DOTNET_ROOT[_arch]并且在诊断信息中会打印DOTNET_ROOT与DOTNET_ROOT_ARCH的取值src/native/corehost/fxr_resolver.c便于排查。5.2 复用 testhost 布局本仓库的 libraries 测试会在libs.pretest子集阶段基于你本地的 runtime、host 与 libraries 构建产物构造一个与 .NET 安装布局一致的目录。从 eng/Subsets.props 可以看到libs.pretest被包含在默认 libraries 子集链libs.sfxlibs.ooblibs.pretest与引导子集host.nativelibs.sfxlibs.pretest中。该布局位于repo_root/artifacts/bin/testhost/netversion-os-configuration-arch使用方式export DOTNET_ROOTrepo_root/artifacts/bin/testhost/netversion-os-configuration-arch dotnet 你的应用.dll例如Linux x64 Debug 构建、net11.0export DOTNET_ROOT$PWD/artifacts/bin/testhost/net11.0-linux-Debug-x64 dotnet myapp.dll设置后应用运行时将通过DOTNET_ROOT定位hostfxr、hostpolicy与运行时详见 host-components.md 中的 Host FXR / Host Policy 职责说明从而直接使用你本地构建的运行时与库无需安装。注意DOTNET_ROOT仅对框架依赖型应用有效自包含应用从应用目录解析hostfxr不受此变量影响。另外dotnetmuxer 本身在其实现注释中明确对 apphost 不支持 DOTNET_ROOT 或不同名称的 dll见 src/native/corehost/dotnet/dotnet.cpp此处的用法是面向应用运行时的宿主解析。六、验证与排错建议确认本地宿主已构建检查artifacts/bin/os-arch.configuration/corehost/下是否存在apphost/singlefilehost缺失时先构建host子集。确认路径书写正确AppHostSourcePath需要完整绝对路径Windows 下注意.exe后缀。单文件场景勿忘PublishSingleFile仅设置SingleFileHostSourcePath而不启用PublishSingleFile不会触发单文件宿主逻辑。验证DOTNET_ROOT生效可临时运行带COREHOST_TRACE1的应用宿主跟踪日志观察fxr_resolver打印的搜索位置与DOTNET_ROOT取值确认命中本地布局。复用宿主测试环境宿主测试docs/workflow/testing/host/testing.md会启动独立进程如dotnet、apphost、native host并校验其标准输出/错误host.pretest子集负责构造测试工程产物与 .NET 安装布局调试时可设置PRESERVE_TEST_RUNS1保留生成的测试工件以便复现。七、总结场景推荐手段关键配置常规应用使用本地 apphostAppHostSourcePath指向artifacts/bin/.../corehost/apphost[.exe]单文件发布使用本地宿主SingleFileHostSourcePathPublishSingleFile指向artifacts/bin/.../corehost/singlefilehost[.exe]框架依赖应用运行于本地布局DOTNET_ROOT指向artifacts/bin/testhost/netversion-os-configuration-arch完整模拟 SDK 默认解析packs / NuGet 缓存 /KnownAppHostPack复制本地产物或本地打包 NuGet 包这三种手段覆盖了从换一个宿主二进制到整体切换运行时布局的常见调试需求可显著缩短在 dotnet/runtime 仓库中迭代宿主与运行时组件时的验证循环。相关宿主组件架构可进一步阅读 docs/design/features/host-components.md宿主测试的构建与运行细节可参考 docs/workflow/testing/host/testing.md。赞分享语言运行时标准库JIT编译编译器【免费下载链接】runtime.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.项目地址https://gitcode.com/GitHub_Trending/runtime6/runtime点击查看免费下载相关推荐使用 CoreRun 与 Core_Root 运行基于本地构建的 .NET 运行时使用 CoreRun 与 Core_Root 运行基于本地构建的 .NET 运行时 导读 本文面向正在为 .NET 运行时仓库runtime repo贡献代语言运行时标准库JIT编译编译器在 .NET 运行时仓库中构建、运行与调试 Android 上的 CoreCLR完整开发者工作流在 .NET 运行时仓库中构建、运行与调试 Android 上的 CoreCLR完整开发者工作流 导读 本文基于 .NET 运行时仓库dotnet/runt语言运行时标准库JIT编译编译器使用 .NET runtime 自构建的 Shipping 包配合开发版 .NET SDK 测试运行时改动使用 .NET runtime 自构建的 Shipping 包配合开发版 .NET SDK 测试运行时改动 本指南以 docs/workflow/testing语言运行时标准库JIT编译编译器创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻