dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.06k forks source link

csproj: HintPath of local assembly reference is ignored #10969

Open andrekoehler opened 4 years ago

andrekoehler commented 4 years ago

Versions

Microsoft Windows [Version 10.0.18363.720] Microsoft Visual Studio Community 2019, Version 16.5.0 dotnet --version => 5.0.100-preview.1.20155.7 Also occurs with 3.1 LTS SDK

How to reproduce:

  1. Unpack and open contained sln file in Visual Studio 2019: Bug.zip
    │   Bug.sln
    │
    ├───MyApp
    │       MyApp.csproj
    │       Program.cs
    │
    └───MyLib
        MyClass.cs
        MyLib.csproj

    MyLib represents any assembly that only exists for x86/x64 but not for Any CPU. This is the case for some C++/CLI assemblies I got from a vendor of USB cameras. MyLib is configured to store the built assemblies inside the MyApp folder. There is no ProjectReference, only Project Build Order to build MyLib before MyApp. After building MyLib, the files look like this:

    │   Bug.sln
    │
    └───MyApp
    │   MyApp.csproj
    │   Program.cs
    │
    └───libs
        ├───x64
        │   └───netstandard1.0
        │           MyLib.dll
        │
        └───x86
            └───netstandard1.0
                    MyLib.dll
  2. Select solution platform "x64" and build. -> builds without warnings
  3. Launch MyApp project (x64) -> runs without exceptions
  4. Select solution platform "x86" and build. -> builds with warnings:
    2>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2081,5): warning MSB3270: There was a mismatch between the processor architecture of the project being built "x86" and the processor architecture of the reference "MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null, ProcessorArchitecture=X86", "AMD64". This mismatch may cause runtime failures. Please consider changing the targeted processor architecture of your project through the Configuration Manager so as to align the processor architectures between your project and references, or take a dependency on references with a processor architecture that matches the targeted processor architecture of your project.
    2>CSC : warning CS8012: Referenced assembly 'MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' targets a different processor.
  5. Launch MyApp project (x86) -> crashes with exception:
    System.BadImageFormatException
    HResult=0x8007000B
    Message=Could not load file or assembly 'MyLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

The reason for this is because the build system ignores the HintPath which points to the x86 version of the assembly and instead uses the x64 version of the assembly, probably because the string "x64" is sorted before "x86". I used ILSpy to verify that "Bug\MyApp\bin**x86\Debug\netcoreapp3.1\MyLib.dll" is indeed the x64** version.

The issue also occurs when using MSBuild from the command line, so it is no specific to Visual Studio:

dotnet build -p:Platform=x86
dotnet build -p:Platform=x64

Failed Workarounds

Successful Workarounds

dsplaisted commented 4 years ago

What happens if instead of using the HintPath, you use the path you want directly in the itemspec, ie:

<Reference Include="libs\x64\netstandard1.0\MyLib.dll" />
andrekoehler commented 4 years ago

@dsplaisted

What happens if instead of using the HintPath, you use the path you want directly in the itemspec, ie:

<Reference Include="libs\x64\netstandard1.0\MyLib.dll" />

Your suggestion works perfectly, thank you!

I had no idea we could just specify the path to the assembly directly in the "Include" attribute, because when adding a reference via Visual Studio, it always adds HintPath for that.

Ghostbird commented 1 year ago

What happens if instead of using the HintPath, you use the path you want directly in the itemspec, ie:

<Reference Include="libs\x64\netstandard1.0\MyLib.dll" />

Solved it for me too! .NET 7.0 MAUI project didn't work with HintPath but this worked perfectly.

mingpepe commented 1 year ago

It takes me a day to find this solution.

andrekoehler commented 1 year ago

The issue still persists with .NET 7.

KalleOlaviNiemitalo commented 1 year ago

In .NET 7, this from https://github.com/dotnet/msbuild/issues/3784 might also work:

<PropertyGroup>
    <AssemblySearchPath_UseCandidateAssemblyFiles>false</AssemblySearchPath_UseCandidateAssemblyFiles>
</PropertyGroup>