Wer bereits die Targets BeforeCompileSolution und AfterCompileSolution verwendet hat, um eigene Aktionen während eines Buildprozesses im TFS auszuführen, wird das Problem kennen. Eigene Properties besitzen keine Werte mehr, sie schein nicht definiert zu sein. Und tatsächlich ist das auch das Problem. Aus Gründen der Rückwärtskompatibilität wird zwischen den Targets BeforeCompile und AfterCompile das Target CallCompile aufgerufen. Dieses nutzt den MSBuild-Task, um CoreCompile aufzurufen, welches letztendlich die SolutionsToBuild kompiliert. Hier ein Code-Ausschnitt aus der Datei Microsoft.TeamFoundation.Build.targets:
<Target Name=”CallCompile” DependsOnTargets=”$(CoreCompileDependsOn)”>
<!– Backwards Compatibility –>
[…]
<!– Pass in all properties that users might want during the course of the compile targets. –>
<MSBuild Projects=”$(MSBuildProjectFile)”
Properties=”BuildAgentName=$(BuildAgentName);BuildAgentUri=$(BuildAgentUri);BuildDefinitionName=$(BuildDefinitionName);BuildDefinitionUri=$(BuildDefinitionUri);
BuildDirectory=$(BuildDirectory);BuildNumber=$(BuildNumber);CompilationStatus=$(CompilationStatus);CompilationSuccess=$(CompilationSuccess);
[…]
SolutionRoot=$(SolutionRoot);BinariesRoot=$(BinariesRoot);TestResultsRoot=$(TestResultsRoot);
$(CustomPropertiesForBuild)”
Targets=”CoreCompile”>
<Output TaskParameter=”TargetOutputs” ItemName=”CompilationOutputs” />
</MSBuild>
<OnError ExecuteTargets=”SetBuildBreakProperties;OnBuildBreak;” />
</Target>
Der durch Team Foundation Build vorgegebene Buildablauf gestaltet sich wie folgt (Einstiegspunkt ist das Target Compile):
Es fällt ein Property namens CustomPropertiesForBuild auf. Tatsächlich dient es dazu, eigene Properties in den Build (Target Compile) “einzuschleusen”. Dazu definiert man spätestens im Target BeforeCompile folgende PropertyGroup:
<PropertyGroup>
<CustomPropertiesForBuild>
MyCustomProperty1=Value1;
MyCustomProperty2=ValueFirstPart%3BValueSecondPart;
</CustomPropertiesForBuild>
</PropertyGroup>
MyCustomProperty2 enthält im Wert ein Semikolon. Dieses würde aber beim Aufruf von MSBuild als Trennungszeichen für das nächste Property interpretiert werden. Daher müssen Semikolons, die im Property enthalten sein sollen (z.B. bei Datenbank-Connection-Strings) mit %3B escaped werden (Kommandozeilen-Escape).
Mit diesen Properties kann man dann in den Targets BeforeCompileSolution und AfterCompileSolution arbeiten…