.csproj multiple hint paths for an assembly

I'm packaging example code for an SDK distribution. In the distribution, the relative path from code to the SDK assemblies is different from the build machine. For example:

Distribution

csharp/bin/assembly.dll
example/ex1/ex1.csproj

Build Machine

foo/sdk/csharp/bin/assembly.dll
bar/baz/quux/ex1/ex1.csproj

Assume that I can't move anything. Is there a way I can instruct ex1.csproj to look in both

../../csharp/bin/ and ../../../../foo/sdk/csharp/bin/ for assembly.dll?

In C++ I'd put the dependency path in a standalone property sheet and distribute a different version with the SDK. But C# doesn't have property sheets, and I don't want to maintain two versions of the full project.

I've seen this question which states that I can't use multiple <HintPath> tags, so I'm looking for another way to approximate the same behavior.


Solution 1:

The simplest way since only ONE HintPath can be used is to use the all-so-nice Condition attribute like this:

<Reference Include="TheAssembly">
    <HintPath Condition="Exists('..\My\Assembly\Path')">..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\My\Assembly\Path')">..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\My\Assembly\Path')">..\..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\..\My\Assembly\Path')">..\..\..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\..\..\My\Assembly\Path')">..\..\..\..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\..\..\..\My\Assembly\Path')">..\..\..\..\..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\..\..\..\..\My\Assembly\Path')">..\..\..\..\..\..\..\My\Assembly\Path\TheAssembly.dll</HintPath>
    etc...
</Reference>

So the answer to the question would be this:

<Reference Include="assembly">
    <HintPath Condition="Exists('..\..\csharp\bin')">..\..\csharp\bin\assembly.dll</HintPath>
    <HintPath Condition="Exists('..\..\..\..\foo\sdk\csharp\bin')">..\..\..\..\foo\sdk\csharp\bin\assembly.dll</HintPath>
</Reference>

If multiple conditions matches, the last one will be used.

Solution 2:

I found a hacky solution that works for my case, where the parent directory is guaranteed to be different somewhere up the tree:

<Choose>
  <When Condition="Exists('$(MSBuildProjectDirectory)\..\..\example')">
    <ItemGroup>
      <Reference Include="Assembly ...">
        <HintPath>..\..\csharp\bin\assembly.dll</HintPath>
      </Reference>
    </ItemGroup>
  </When>
  <Otherwise>
    <ItemGroup>
      <Reference Include="Assembly ...">
         <HintPath>..\..\..\..\..\foo\sdk\csharp\bin\assembly.dll</HintPath>
      </Reference>
    </ItemGroup>
  </Otherwise>
</Choose>

Solution 3:

Add the secondary path as follows to the general property group. in the csproj file

<PropertyGroup>
    <ReferencePath>..\..\..\..\..\foo\sdk\csharp\bin\</ReferencePath>
    ...
</PropertyGroup>

The ReferencePath property is intended to be specified when executing MsBuild, but it will work fine like this.

Solution 4:

I am using this solution without any problem:

<Reference Include="log4net">
  <HintPath>
     $(SolutionDir)packages\log4net.2.0.8\lib\net45-full\log4net.dll
  </HintPath>
</Reference>

Got it from here: use hint paths relative answer from LeonidVasilyev