Search code examples
c#.netnuget-package

Migrating to .csproj SDK breaks import of dlls from nuget package


Recently I tried to upgrade my .csproj files to SDK standard using .net upgrade assistant. Initially it seems to work and all my nuget dependencies came along for the ride.

However when I try to build my project (targeting .net48) the dlls from the nuget package are not included in the output directory. I've been looking for solutions around the web, but most of them seem to indicate that they should be present. The specific package I'm having problems with is RavenDB.Database v2.5.25041. It is part of a test suite that needs this specific version so I cannot unfortunately upgrade it. The tests also do not run and complain about missing assemblies unless the dlls are present in the output directory (testet by manually copying them).

Running a build on the project before the SDK-migration works fine and the output directory includes those dlls. Does anyone know why this work differently in the new version and how can I resolve it?

Edit:

This is the .csproj file after conversion:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net48</TargetFramework>
    <OutputType>Library</OutputType>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System.Data.Services.Client" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="EntityFramework" Version="6.4.4" />
    <PackageReference Include="RavenDB.Database" Version="2.5.25041" />
    <PackageReference Include="RavenDB.Embedded" Version="2.5.25041" />
  </ItemGroup>
</Project>

Edit2:

The .csproj file before conversion (warning, big):

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="..\..\packages\EntityFramework.6.4.4\build\EntityFramework.props" Condition="Exists('..\..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" />
  <Import Project="..\..\packages\JunitXml.TestLogger.2.1.81\build\net45\JUnitXml.TestLogger.props" Condition="Exists('..\..\packages\JunitXml.TestLogger.2.1.81\build\net45\JUnitXml.TestLogger.props')" />
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProjectGuid>{7A3590CE-A43F-4A69-B520-27402FDD9F87}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>Sti.TestUtils</RootNamespace>
    <AssemblyName>Sti.TestUtils</AssemblyName>
    <TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
    <Deterministic>true</Deterministic>
    <NuGetPackageImportStamp>
    </NuGetPackageImportStamp>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
      <HintPath>..\..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.dll</HintPath>
    </Reference>
    <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
      <HintPath>..\..\packages\EntityFramework.6.4.4\lib\net45\EntityFramework.SqlServer.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Data.Edm, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\packages\Microsoft.Data.Edm.5.2.0\lib\net40\Microsoft.Data.Edm.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.Data.OData, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\packages\Microsoft.Data.OData.5.2.0\lib\net40\Microsoft.Data.OData.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.WindowsAzure.Configuration, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\packages\Microsoft.WindowsAzure.ConfigurationManager.1.8.0.0\lib\net35-full\Microsoft.WindowsAzure.Configuration.dll</HintPath>
    </Reference>
    <Reference Include="Microsoft.WindowsAzure.Storage, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\packages\WindowsAzure.Storage.2.0.0.0\lib\net40\Microsoft.WindowsAzure.Storage.dll</HintPath>
    </Reference>
    <Reference Include="Raven.Abstractions, Version=2.5.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
      <HintPath>..\..\packages\RavenDB.Client.2.5.25041\lib\net45\Raven.Abstractions.dll</HintPath>
    </Reference>
    <Reference Include="Raven.Client.Embedded, Version=2.5.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
      <HintPath>..\..\packages\RavenDB.Embedded.2.5.25041\lib\net45\Raven.Client.Embedded.dll</HintPath>
    </Reference>
    <Reference Include="Raven.Client.Lightweight, Version=2.5.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
      <HintPath>..\..\packages\RavenDB.Client.2.5.25041\lib\net45\Raven.Client.Lightweight.dll</HintPath>
    </Reference>
    <Reference Include="Raven.Database, Version=2.5.0.0, Culture=neutral, PublicKeyToken=37f41c7f99471593, processorArchitecture=MSIL">
      <HintPath>..\..\packages\RavenDB.Database.2.5.25041\lib\net45\Raven.Database.dll</HintPath>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.ComponentModel.Composition" />
    <Reference Include="System.ComponentModel.DataAnnotations" />
    <Reference Include="System.Core" />
    <Reference Include="System.Data.Services.Client" />
    <Reference Include="System.Spatial, Version=5.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
      <HintPath>..\..\packages\System.Spatial.5.2.0\lib\net40\System.Spatial.dll</HintPath>
    </Reference>
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Program.cs" />
  </ItemGroup>
  <ItemGroup>
    <None Include="app.config" />
    <None Include="packages.config" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\..\packages\JunitXml.TestLogger.2.1.81\build\net45\JUnitXml.TestLogger.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\JunitXml.TestLogger.2.1.81\build\net45\JUnitXml.TestLogger.props'))" />
    <Error Condition="!Exists('..\..\packages\EntityFramework.6.4.4\build\EntityFramework.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\EntityFramework.6.4.4\build\EntityFramework.props'))" />
    <Error Condition="!Exists('..\..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\EntityFramework.6.4.4\build\EntityFramework.targets'))" />
  </Target>
  <Import Project="..\..\packages\EntityFramework.6.4.4\build\EntityFramework.targets" Condition="Exists('..\..\packages\EntityFramework.6.4.4\build\EntityFramework.targets')" />
</Project>

Solution

  • I managed to find a workaround for this specific case. Since the dlls are downloaded as part of the nuget package you can force dotnet to include them in the build output by adding the following to the .csproj file of the final assembly. Meaning the assembly that is actually built to an executable.

    Add the package reference and set GeneratePathProperty to true.

    <PackageReference Include="RavenDB.Database" Version="2.5.25041">
      <GeneratePathProperty>True</GeneratePathProperty>
    </PackageReference>
    

    Then reference the missing dlls using the generated path property.

    <ItemGroup>
    <Reference Include="Esent.Interop">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\Esent.Interop.dll</HintPath>
    </Reference>
    <Reference Include="ICSharpCode.NRefactory">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\ICSharpCode.NRefactory.dll</HintPath>
    </Reference>
    <Reference Include="ICSharpCode.NRefactory.CSharp">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\ICSharpCode.NRefactory.CSharp.dll</HintPath>
    </Reference>
    <Reference Include="Lucene.Net">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\Lucene.Net.dll</HintPath>
    </Reference>
    <Reference Include="Lucene.Net.Contrib.Spatial.NTS">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\Lucene.Net.Contrib.Spatial.NTS.dll</HintPath>
    </Reference>
    <Reference Include="Spatial4n.Core.NTS">
      <HintPath>$(PkgRavenDB_Database)\lib\net45\Spatial4n.Core.NTS.dll</HintPath>
    </Reference>
    

    This will point the build tools to the dlls regardless of where it saves downloaded nuget packages. Read more about GeneratePathProperty on msdocs