如何在解决方案打开时仅执行一次Props文件中的命令?
实现MSBuild Target仅在解决方案打开/变更时执行一次
核心思路
通过标记文件+条件判断实现:创建一个标记文件记录初始化状态,只有当标记文件不存在、NuGet包的props文件更新或解决方案文件变更时,才执行目标命令;执行完成后更新标记文件的时间戳,确保后续构建不再重复运行。
具体实现代码
在你的NuGet包props文件中添加以下配置:
<PropertyGroup> <!-- 定义标记文件路径:优先放在解决方案根目录,单个项目构建时用项目根目录 --> <ToolsInitializedMarkerFile> $(IfExists('$(SolutionDir)', '$(SolutionDir).tools_initialized', '$(MSBuildProjectDirectory).tools_initialized')) </ToolsInitializedMarkerFile> <!-- 判断是否需要执行初始化的条件 --> <NeedRunInitialization> !Exists($(ToolsInitializedMarkerFile)) Or $([System.IO.File]::GetLastWriteTime($(MSBuildProjectFile))).Ticks > $([System.IO.File]::Exists($(ToolsInitializedMarkerFile)) ? [System.IO.File]::GetLastWriteTime($(ToolsInitializedMarkerFile)).Ticks : 0) Or $([System.IO.Directory]::Exists($(SolutionDir)) ? $([System.IO.File]::GetLastWriteTime($(SolutionDir)*.sln)).Ticks : 0) > $([System.IO.File]::Exists($(ToolsInitializedMarkerFile)) ? [System.IO.File]::GetLastWriteTime($(ToolsInitializedMarkerFile)).Ticks : 0) </NeedRunInitialization> </PropertyGroup> <Target Name="_myRunCommands" BeforeTargets="Build;Rebuild" Condition="$(NeedRunInitialization)"> <!-- 执行你的初始化命令 --> <Exec Command="dotnet tool restore" /> <Exec Command="dotnet tool update husky csharpier" /> <Exec Command="dotnet husky install" /> <!-- 创建/更新标记文件,标记已完成初始化 --> <Touch Files="$(ToolsInitializedMarkerFile)" AlwaysCreate="true" /> </Target>
关键细节说明
- 标记文件位置:默认放在解决方案根目录(
.tools_initialized),确保整个解决方案共享初始化状态,不会每个项目单独执行;如果是单个项目构建,则自动切换到项目根目录。 - 触发条件:
- 标记文件不存在:首次打开解决方案/项目时执行
- NuGet包的props文件更新:升级NuGet包时自动重新执行初始化
- 解决方案文件变更:添加/移除项目、修改解决方案配置时重新执行初始化
- 避免重复执行:
Touch任务会更新标记文件的修改时间,后续构建时条件不满足,不会再次执行目标。
可选调整
如果希望清理解决方案后不重新执行初始化,可以将标记文件放在不会被清理的目录,比如:
<ToolsInitializedMarkerFile>$(SolutionDir).nuget/.tools_initialized</ToolsInitializedMarkerFile>
默认的Clean操作不会删除.nuget目录下的文件,能保留初始化标记。
内容的提问来源于stack exchange,提问作者SpaceGhost440
相关产品推荐
相关产品推荐

