MSBuild中Exists条件已存在文件仍判定为false(缓存问题?)
解决MSBuild内部构建中
Exists()缓存导致targets无法导入的问题 问题分析
你遇到的是MSBuild文件系统查找缓存机制引发的问题:顶级<Import>的Exists()检查在项目加载阶段执行,结果被缓存;内部构建复用了父构建的缓存值,即便父构建刚创建了目标文件,内部构建仍判定文件不存在,最终导致导入失败。
解决方案
方案1:禁用文件系统查找缓存
MSBuild提供DisableFileSystemLookupCache属性,将其设为true可关闭Exists()等文件检查的缓存,让每次检查都直接访问文件系统。
修改内部构建的MSBuild任务,添加该属性:
<Target Name="DoInnerBuild" BeforeTargets="CoreCompile" DependsOnTargets="CreateExternalTargetsFile"> <MSBuild Projects="$(MSBuildProjectFile)" Targets="InnerBuildTarget" Properties="DisableFileSystemLookupCache=true" /> </Target>
注意:禁用缓存会带来轻微性能损耗,适合文件操作不多的场景。
方案2:延迟导入到目标执行阶段
将顶级<Import>替换为在目标中使用ImportProject任务动态导入,避开项目加载阶段的缓存。
修改项目文件:
- 移除原有的顶级
<Import>节点 - 添加一个用于导入的目标,在内部构建目标执行前触发:
<Target Name="ImportExternalTargets" BeforeTargets="InnerBuildTarget" Condition="Exists('$(ExternalTargetsFilePath)')"> <ImportProject Project="$(ExternalTargetsFilePath)" /> </Target>
这样内部构建执行InnerBuildTarget前会重新检查文件状态并导入,不会复用之前的缓存结果。
方案3:直接传递属性(适合简单场景)
如果外部targets文件仅用于设置属性,可跳过文件导入,直接将属性传递给内部构建,完全规避缓存问题:
<Target Name="DoInnerBuild" BeforeTargets="CoreCompile" DependsOnTargets="CreateExternalTargetsFile"> <MSBuild Projects="$(MSBuildProjectFile)" Targets="InnerBuildTarget" Properties="ExternalProperty=2" /> </Target>
该方案最简洁,适合不需要复杂targets逻辑的场景。
测试验证
应用上述任意方案后,首次构建即可成功执行InnerBuildTarget,不会再触发自定义错误。
内容的提问来源于stack exchange,提问作者Dark Daskin
相关产品推荐
相关产品推荐

