Once again I\'m battling MSBuild. I want to have a property value defined with a root path. As part of the build, the path will get updated with version information. Howe
Building on sll's answer, making the target that sets the new path a dependency instead of using CallTarget will yield the expected behaviour:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<MyPath>\\server\folder</MyPath>
</PropertyGroup>
<Target Name="Main" DependsOnTargets="SetMyPathProperty">
<Message Text="In Main Before - MyPath = $(MyPath)"/>
<CallTarget Targets="Task1" />
<Message Text="In Main After - MyPath = $(MyPath)"/>
</Target>
<Target Name="SetMyPathProperty">
<PropertyGroup>
<MyPath>$(MyPath)\version5</MyPath>
</PropertyGroup>
</Target>
<Target Name="Task1">
<Message Text="In Task1 - MyPath = $(MyPath)"/>
</Target>
</Project>
Build Output:
Main:
In Main Before - MyPath = \\server\folder\version5
Task1:
In Task1 - MyPath = \\server\folder\version5
Main:
In Main After - MyPath = \\server\folder\version5
Making SetMyPathProperty a dependency of Task1 instead of Main will result in identical behaviour to your PropertyScopeTest1.proj.
This is a very interesting question which is investigated deeply with examples in following article: Scope of properties and item in an MSBuild script
Basically there are tricks with a local and global context switches across a target executions:
- One instance of the Project class is created for the script and contains all the values of the properties and items in a global context.
- When a target is executed, the global context is copied in a local context which will be used by the target.
- A the target execution end, the local context updates are merged back to the global context.
- Until a target execution is finished the local updates are not accessible to targets called using CallTarget or MSBuild tasks