dotnet run 有启动钩子,watch 却没有:检查 STARTUP_HOOKS 被覆盖
dotnet watch 热重载入口可能覆盖现有 DOTNET_STARTUP_HOOKS。若确需在开发时保留钩子,可评估通过项目 runtimeconfig 声明,并确认钩子在应用进程执行。
同一个应用,dotnet run 能执行 APM 或诊断启动钩子,改用 dotnet watch run 后钩子消失,应用本身仍正常启动。先确认钩子是否真的在应用进程执行,而不是只在外层 dotnet 或 dotnet-watch 进程出现过日志。
SDK 10.0.301、11.0.100-preview.7.26381.103 在 Ubuntu x64 的具体场景中,来自父环境或 launchSettings.json 的 DOTNET_STARTUP_HOOKS 都可能被热重载代理的环境值覆盖。反复把同一个值加回 launch profile,不一定能越过这条启动路径。
比较应用最终收到的钩子列表
在隔离开发环境,对比普通运行和 watch 运行时的有效 STARTUP_HOOKS,并核对钩子的应用内初始化标记。外层环境变量存在,只证明启动 watch 之前的值,不能证明子应用最终保留它。
检查时不要输出程序集中的凭据、完整跟踪数据或其他敏感配置。钩子属于进程启动代码,必须使用项目已信任的程序集;不要把临时下载的 DLL 加进诊断入口。
可控项目可以在 runtimeconfig 声明
项目允许修改且目标运行时支持时,可通过 MSBuild 项把钩子写入生成的 runtimeconfig。下面是 .csproj 局部结构:
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<RuntimeHostConfigurationOption
Include="STARTUP_HOOKS"
Value="/absolute/path/to/Hook.dll" />
</ItemGroup>
路径是占位值,替换为开发环境实际可读的可信程序集。这个条件仅限定 Debug,并不自动保证调试产物永远不会被部署;仍需审查生成文件和交付流程。多人开发或 CI 应使用各自受控配置生成路径,不要把某台机器的私有目录硬编码成全项目依赖。
这条绕行利用 STARTUP_HOOKS 的专门合并路径:正式运行时 10.0.12 会把配置中的钩子追加到环境钩子之后。这不应推广为所有 runtimeconfig 设置都与环境变量合并。需要同时保留原有热重载代理与业务诊断钩子,不能直接移除代理来换取一个初始化日志。不能改项目的外部诊断工具,则需要使用它支持的其他入口,不应偷偷修改被观测项目。
验证生成的 .runtimeconfig.json 含预期项,再由 watch 启动应用,确认钩子在应用入口所在进程执行,热重载及原功能也仍可用。最后检查正式发布配置没有残留开发机路径。撤回时同时移除项目项与相应生成配置,不把已生成文件的手工编辑当成长期方案。


