views:

393

answers:

1

Dear ladies ... and sirs.

I have the following msbuild script:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"
         DefaultTargets="All">

  <PropertyGroup>
  ...
  </PropertyGroup>

  <UsingTask AssemblyFile="$(GallioTaskPath)" TaskName="Gallio.MSBuildTasks.Gallio" />
  <Import Project="$(MSBuildCommunityTasksPath)\MSBuild.Community.Tasks.Targets" />

  <ItemGroup>
  ...
  </ItemGroup>

  <Target Name="CheckServerHostsItemGroup"
          Condition="'$(NoServerHosts)' != True">
  ...
  </Target>

  <Target Name="RunServerHosts" DependsOnTargets="CheckServerHostsItemGroup"
          Condition="'$(NoServerHosts)' != True">
  ...
  </Target>

  <Target Name="KillServerHosts" DependsOnTargets="CheckServerHostsItemGroup"
          Condition="'$(NoServerHosts)' != True">
    ...
  </Target>

  <Target Name="KillServerHosts2"
          Condition="'$(NoServerHosts)' != True">
    <MSBuild Projects="$(MSBuildProjectFile)" Targets="KillServerHosts" Properties="Configuration=$(Configuration)" />
  </Target>

  <Target Name="All" DependsOnTargets="Build;RunServerHosts;Test;KillServerHosts2">
    <OnError ExecuteTargets="KillServerHosts2" />
  </Target>

  <Target Name="Test">
    ...
    <Error Text="Tests execution failed with exit code $(ExitCode)" Condition="'$(ExitCode)' != 0" />
  </Target>

  <Target Name="CheckSolutionsItemGroup">
  ...
  </Target>

  <Target Name="Build" DependsOnTargets="CheckSolutionsItemGroup;KillServerHosts">
  ...
  </Target>

  <Target Name="Clean" DependsOnTargets="CheckSolutionsItemGroup;KillServerHosts">
  ...
  </Target>

</Project>

I have removed the bodies of the targets to save space and because they are irrelevant. However, if someone thinks they are, I will include them.

Anyway, as one can see, there is one target - KillServerHosts, which I wish to invoke twice and for a good reason. Once before the build, in order to ensure no assemblies are locked and the other time after the tests complete to "cleanup the table".

Naturally, trying to invoke the target KillServerHosts twice does not work, MSBuild refuses to build the same target twice. So, I am trying to cheat by invoking the target KillServerHosts2. The problem is that sometimes it works and sometimes it does not.

If I run the KillServerHosts target from the command line it always kills the relevant server hosts, so from this respect it works fine.

Any ideas?

+2  A: 

By design MSBuild targets are not executed more than once. You should not think of an MSBuild target as a method or function, bucause MSBuild is not a functional programming language.

If you want to execute a target more than once you can use the MSBuild task to do so, just pass in a different set of properties. For example something like this

<Target Name="SomeTarget">
    <MSBuild Project="$(MSBuildProjectFile)" Targets="YourTarget" Properties="FakeProperty=one" />
    <MSBuild Project="$(MSBuildProjectFile)" Targets="YourTarget" Properties="FakeProperty=two" />
</Target>

Note: I didn't actually try this out so there might be syntax issues if I mis-spelled or remembered incorrectly but you should be able to get it working.

Sayed Ibrahim Hashimi