如何从另一个项目的Target中获取动态设置的属性?
在MSBuild中跨项目传递属性值的解决方案
问题场景
b.msbuildproj的Target A调用a.msbuildproj的Target A,后者在Target中设置了PropA属性,需要在b项目中获取该属性的值。实际业务背景是:用户搭建了一个appx打包项目,用于打包桌面应用和应用项目,应用项目中有一个Target会生成版本号,需要在打包项目中使用该版本号。已知无法直接从另一个项目的Target返回属性,需通过MSBuild解决此问题。
原代码示例
a.msbuildproj:
... <Target Name="A"> <PropertyGroup> <PropA>a</PropA> </PropertyGroup> </Target> ...
b.msbuildproj:
... <Target Name="A"> <MSBuild Project="a.msbuildproj" Target="A"/> <Message Text="$(PropA)"/> </Target> ...
解决方案
方法1:使用MSBuild任务的Output参数传递属性
这是跨项目传递属性最直接的官方方式,通过在被调用项目的Target中声明输出,调用方通过Output节点接收。
修改a.msbuildproj的Target:
<Target Name="A"> <PropertyGroup> <PropA>a</PropA> </PropertyGroup> <!-- 将PropA声明为Target的输出属性 --> <Output TaskParameter="PropertyGroup.PropA" PropertyName="PropA" /> </Target>
修改b.msbuildproj的Target:
<Target Name="A"> <MSBuild Project="a.msbuildproj" Target="A"> <!-- 接收a项目Target输出的PropA,重命名避免冲突 --> <Output TaskParameter="TargetOutputs.PropA" PropertyName="PropAFromA" /> </MSBuild> <Message Text="从a项目获取的PropA值:$(PropAFromA)" /> </Target>
方法2:通过中间属性文件传递
如果属性生成逻辑复杂,或者需要共享给多个项目,可以让被调用项目将属性写入临时文件,调用项目再导入该文件读取属性。
修改a.msbuildproj的Target:
<Target Name="A"> <PropertyGroup> <PropA>a</PropA> <PropFilePath>$(MSBuildProjectDirectory)/temp.props</PropFilePath> </PropertyGroup> <!-- 将属性写入临时文件 --> <WriteLinesToFile File="$(PropFilePath)" Lines="<PropertyGroup><PropA>$(PropA)</PropA></PropertyGroup>" Overwrite="true" Encoding="UTF-8"/> </Target>
修改b.msbuildproj的Target:
<Target Name="A"> <PropertyGroup> <PropFilePath>$(MSBuildProjectDirectory)/temp.props</PropFilePath> </PropertyGroup> <MSBuild Project="a.msbuildproj" Target="A"/> <!-- 导入临时属性文件 --> <Import Project="$(PropFilePath)" Condition="Exists('$(PropFilePath)')"/> <Message Text="从属性文件读取的PropA值:$(PropA)" /> </Target>
方法3:使用全局属性(不推荐)
可以通过在MSBuild任务中传递全局属性,但这种方式会将属性设置为全局范围,可能影响后续所有项目的构建,仅适合特殊场景。
修改b.msbuildproj的Target:
<Target Name="A"> <MSBuild Project="a.msbuildproj" Target="A" Properties="GlobalPropA=$(PropA)"/> <Message Text="全局属性PropA值:$(GlobalPropA)" /> </Target>
修改a.msbuildproj的Target:
<Target Name="A"> <PropertyGroup> <PropA>a</PropA> <!-- 将本地属性赋值给全局属性 --> <GlobalPropA>$(PropA)</GlobalPropA> </PropertyGroup> </Target>
方案选择
- 优先使用方法1,逻辑清晰且符合MSBuild设计规范,无副作用。
- 当需要跨多个项目共享属性,或属性生成逻辑依赖文件输出时,选择方法2。
- 方法3尽量避免使用,防止全局属性污染构建上下文。
内容的提问来源于stack exchange,提问作者lulle2007200
相关产品推荐
相关产品推荐

