'Azure DevOps build task VSBuild copies DLL marked as copy=false

I'm currently trying to create a CD pipeline with Azure DevOps with a solution using .NET Framework 4.8 and Oracle. Unfortunately, I can't make it run; as the DLL Oracle.DataAccess is in the GAC, I need to make sure the build-pipeline doesn't package it, otherwise I get the error:

Could not load file or assembly 'Oracle.DataAccess, Version=4.121.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Now, what's interesting: To make it work locally, I have the Oracle.DataAccess DLL copied to a local folder, but reference it with "Copy Local = False":

    <Reference Include="Oracle.DataAccess, Version=4.122.19.1, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=AMD64">
      <SpecificVersion>False</SpecificVersion>
      <HintPath>..\..\librairies\Oracle.DataAccess.dll</HintPath>
      <Private>False</Private>
    </Reference>

Now, when compiling locally, everything is fine and the DLL is not copied locally, but when I build on Azure DevOps, I always get the DLL in the final package and I see the following log-entry:

_CopyFilesMarkedCopyLocal: Copying file from "C:...\19.0.0\client_1\odp.net\bin\4\Oracle.DataAccess.dll" to "Path\bin\Release\Oracle.DataAccess.dll".

The Azure DevOps YAML looking like this:

variables:
  solution: 'src/**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'

steps:
...
- task: VSBuild@1
  displayName: 'Build solution'
  inputs:
    solution: '$(solution)'
    vsVersion: '16.0'
    msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
    platform: '$(buildPlatform)'
    configuration: '$(buildConfiguration)'
    msbuildArchitecture: 'x64'
    createLogFile: true

Checking with TotalCmd and the likes, I don't see any hidden dependency to the Oracle.DataAccess DLL in the codebase. It seems like the VSBuild Task kinda how wants to copy the file anyway, although me saying it shouldn't. Is there anything I'm not seeing hereby? Or is there a significant difference in how the VSBuild task behaves? I didn't find anything specific in the documentation about such behavior.



Solution 1:[1]

As workaround you could delete the file manually. Edit your .csproj with a text editor and add this line:

<Target Name="AfterBuild">
  <Delete Files="$(OutputPath)Oracle.DataAccess.dll" />
</Target>

See Extend the Visual Studio build process

Solution 2:[2]

I randomly found a solution, but I'm not sure if it's a hack or intended. When I configure the referenced assembly directly in the host assembly like this:

      <Reference Include="Oracle.DataAccess, Version=x.x.x.x, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=AMD64">
          <SpecificVersion>False</SpecificVersion>
          <HintPath>..\..\librairies\Oracle.DataAccess.dll</HintPath>
          <Private>False</Private>
      </Reference>

It works out and the publishing doesn't copy it. I would tend to think this is a bug of the task kinda how, as locally publish doesn't copy the assembly and I would guess, that having a transient dependency with copy=false should honor this as well. Also, having a reference to the data access assembly in the host assembly (like web API) isn't a nice separation of concerns.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Wernfried Domscheit
Solution 2 Matthias Müller