MSBuild passing parameters to CallTarget

MsbuildParameter PassingMsbuild Target

Msbuild Problem Overview


I'm trying to make a reusable target in my MSBuild file so I can call it multiple times with different parameters.

I've got a skeleton like this:

<Target Name="Deploy">
    <!-- Deploy to a different location depending on parameters -->
</Target>

<Target Name="DoDeployments">
    <CallTarget Targets="Deploy">
        <!-- Somehow indicate I want to deploy to dev -->
    </CallTarget>

    <CallTarget Targets="Deploy">
        <!-- Somehow indicate I want to deploy to testing -->
    </CallTarget>
</Target>

But I can't work out how to allow parameters to be passed into the CallTarget, and then in turn the Target itself.

Msbuild Solutions


Solution 1 - Msbuild

MSBuild targets aren't designed to receive parameters. Instead, they use the properties you define for them.

<PropertyGroup>
    <Environment>myValue</Environment>
</PropertyGroup>

<Target Name="Deploy">
    <!-- Use the Environment property -->
</Target>

However, a common scenario is to invoke a Target several times with different parameters (i.e. Deploy several websites). In that case, I use the MSBuild MSBuild task and send the parameters as Properties:

<Target Name="DoDeployments">
    <MSBuild Projects ="$(MSBuildProjectFullPath)"
	         Properties="VDir=MyWebsite;Path=C:\MyWebsite;Environment=$(Environment)"
             Targets="Deploy" />

	<MSBuild Projects ="$(MSBuildProjectFullPath)"
	         Properties="VDir=MyWebsite2;Path=C:\MyWebsite2;Environment=$(Environment)"
             Targets="Deploy" />
</Target>

$(MSBuildProjectFullPath) is the fullpath of the current MSBuild script in case you don't want to send "Deploy" to another file.

Hope this helps!

Solution 2 - Msbuild

You can 'foreach' over an ItemGroup with a target, only you have to do it in declaritive manner. You can even have additional metadata in items, like in the code example:

<ItemGroup>
	<What Include="Dev">
		<How>With bugs</How>
	</What>
	<What Include="Test">
		<How>With tests</How>
	</What>
	<What Include="Chicken">
		<How>Deep fried</How>
	</What>
</ItemGroup>

<Target Name="Deploy">
	<Message Text="@(What), %(How)" />
</Target>

Using an item group as a scalar value @(What) inside a target does the trick, and %(How) references a metadata element in a foreach item.

It's a natural way of doing things in msbuild, for example you can find this pattern everywhere in project files generated with Visual Studio.

Solution 3 - Msbuild

There might be a better way to do this in MSBuild, but in Ant, I would use global properties to carry information from one task to the next. It was a lousy solution, but I didn't see a better way at the time. You should be able to do this in MSBuild, but bear in mind that you will need to use the CreateProperty task to dynamically assign a property.

On the other hand, it's pretty easy to implement tasks in C# (or VB or whatever). Maybe that's a better solution for you.

Solution 4 - Msbuild

	<CreateProperty
        Value="file1">
        <Output
            TaskParameter="Value"
            PropertyName="filename" />
    </CreateProperty>
	<CallTarget Targets="Deploy"/>
	<Message Text="$(filename)"/>
	<CreateProperty
        Value="file2">
        <Output
            TaskParameter="Value"
            PropertyName="filename" />
    </CreateProperty>
	<Message Text="$(filename)"/>	
	<CallTarget Targets="Deploy"/>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAaron PowellView Question on Stackoverflow
Solution 1 - MsbuildocentenoView Answer on Stackoverflow
Solution 2 - MsbuildGeorge PolevoyView Answer on Stackoverflow
Solution 3 - MsbuildDaniel YankowskyView Answer on Stackoverflow
Solution 4 - MsbuildMing JiaView Answer on Stackoverflow