Question

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.

Was it helpful?

Solution

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!

OTHER TIPS

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.

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.

    <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"/>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top