Search code examples
msbuildbuild-automationnugetnuget-package

Get NuGet package folder in MSBuild


I want to call executable tools like NUnit which I manage via NuGet in MSBuild:

<Target Name="Test">
  <CreateItem Include="$(BuildCompileDirectory)\*.Tests.*dll">
    <Output TaskParameter="Include" ItemName="TestAssemblies" />
  </CreateItem>
  <NUnit
    Assemblies="@(TestAssemblies)"
    ToolPath="$(PackagesDirectory)\NUnit.2.5.10.11092\tools"
    WorkingDirectory="$(BuildCompileDirectory)"
    OutputXmlFile="$(BuildDirectory)\$(SolutionName).Tests.xml" />
</Target>

The problem is that the folder of a NuGet packages is containing the version number of the package. For instance nunit-console.exe is in the folder packages\NUnit.2.5.10.11092\tools. If I update the NUnit package this path will change and I have to update my MSBuild script. That isn't acceptable.

MSBuild doesn't allow Wildcards in directories, so this isn't working:

ToolPath="$(PackagesDirectory)\NUnit.*\tools"

How can I call tools in MSBuild without having to update my build script whenever I update a NuGet package?


Solution

  • You can use MSBuild Transforms to get the relative directory of a specific tool:

    <ItemGroup>
      <NunitPackage Include="$(PackagesDirectory)\NUnit.*\tools\nunit-console.exe"/>
    </ItemGroup>
    
    <Target Name="Test">
      <CreateItem Include="$(BuildCompileDirectory)\*.Tests.*dll">
        <Output TaskParameter="Include" ItemName="TestAssemblies" />
      </CreateItem>
      <NUnit
        Assemblies="@(TestAssemblies)"
        ToolPath="@(NunitPackage->'%(relativedir)')"
        WorkingDirectory="$(BuildCompileDirectory)"
        OutputXmlFile="$(BuildDirectory)\$(SolutionName).Tests.xml" />
    </Target>