将引用的项目DLL包含在Nuget包中[.Net Core RC3 *.csproj文件]

37

我有一个包含两个项目的解决方案。第一个项目叫做Library1,它引用了第二个项目Referencelibrary。我正在尝试将Referencelibrary的DLL嵌入到Library1的NuGet包中,这样我就不必发布两个单独的NuGet包了。通过将以下条目添加到我的csproj文件中,我已经能够将ReferenceLibrary的DLL嵌入到NuGet包中(好像是这样):

  <ItemGroup>
    <ProjectReference Include="..\ReferenceLibrary\ReferenceLibrary.csproj">
        <ReferenceOutputAssembly>true</ReferenceOutputAssembly>
        <IncludeAssets>ReferenceLibrary.dll</IncludeAssets>
        <IncludeAssets>ReferenceLibrary.pdp</IncludeAssets>
    </ProjectReference>
  </ItemGroup>
但是当我导入NuGet包并尝试运行我的测试应用程序时,我会收到以下异常:Exception Screenshot 我假设DLL已被嵌入,因为在添加“IncludeAssets”到csproj之前,我无法导入NuGet包,因为它试图引用ReferenceLibrary NuGet包。但是在添加这些条目后,它允许我导入它。但现在在运行时出现问题。任何帮助都将不胜感激。谢谢!;)

这对你来说为什么如此重要?因为我不想发布两个单独的NuGet包。 - Jeroen Heier
这个问题有任何更新吗?你从Leo的建议中得到了有用的信息吗? - Weiwei
1
嗨Jeroen,因为我通常对我的所有代码使用分层方法。我经常做的一件事是将数据访问层与其他层分开。因此,在这种特定情况下,我不想发布单独的存储库NuGet包。 - Zorthgo
@Wendy - MSFT - 不是很好,即使尝试了Leo的建议,我仍然收到System.IO.FileNotFoundException错误消息。 - Zorthgo
5个回答

38

现在有一个更加最新的解决方法,描述在这里。只需按照下面所示将TargetsForTfmSpecificBuildOutputTarget节点添加到您的.csproj文件中即可。

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
  </PropertyGroup>
  <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
    <ItemGroup>
      <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
    </ItemGroup>
  </Target>
</Project>

在包目标中,此扩展点的官方文档可以在这里找到。

如果您不想让该项目作为NuGet依赖项出现在生成的软件包中,则可能希望将属性PrivateAssets="All"添加到ProjectReference元素中,例如:

<ProjectReference Include="MyNonNugetDependentProject.csproj" PrivateAssets="All" />

3
这在确保所需的 DLL 最终出现在 NuGet 包的 lib 文件夹方面表现良好,但现在在使用此包时,它会寻找与 DLL 名称相同的 NuGet 包,而不是使用生成的那个。 - JustAnotherDeveloper
2
@JustAnotherDeveloper,这是因为你的DLL仍然在生成的nuspec文件中,需要在项目引用中添加PrivateAssets="all"属性来解决此问题(请参考相关答案中的github链接中的完整示例)。 - viktor.kudria
谢谢!你为我节省了大量的时间。 - Kiran
1
如果我有两个ProjectReferences并且想保留一个作为nugget引用并包含第二个,该怎么办? - macwier

10

这似乎是 Visual Studio 2017 中针对核心项目的内置 NuGet 打包存在已知限制,并在此处进行了讨论:

https://github.com/NuGet/Home/issues/3891

在该讨论线程中,有一个对我有效的解决方法:

https://github.com/NuGet/Home/issues/3891#issuecomment-309792369

<ItemGroup>
  <_PackageFiles Include="$(OutputPath)\ReferencedProjectDll.dll">
    <BuildAction>None</BuildAction>
    <PackagePath>lib\net45\</PackagePath>
  </_PackageFiles>
</ItemGroup>

请注意,您需要更改程序集名称,可能还需要更改包路径以匹配您正在使用的.NET Framework版本。上面的示例适用于4.5,但您可能在更新的4.6上。


1
现在在GitHub上的那个问题中有一个更为最新的解决方法,我已经将其发布为答案这里 - Neo

3
为了将DLL放置在我选择的文件夹中,我使用了MicroSoft描述的另一个自定义点(链接)。因此,我最终得到了以下内容:
<PropertyGroup>
  <IncludeBuildOutput>false</IncludeBuildOutput> <!-- omit the package creating library itself -->
  <PackProject>true</PackProject>
  <TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);CreatePackNupkg</TargetsForTfmSpecificContentInPackage>
</PropertyGroup>

<Target Name="CreatePackNupkg">
  <ItemGroup>
    <TfmSpecificPackageFile Include="$(OutputPath)\<whatever>.*.dll">
      <PackagePath>folder/subfolder</PackagePath>
    </TfmSpecificPackageFile>
  </ItemGroup>    
</Target>

NuGet.Pack包的创建方式与之前相同,可以参考(这里)。

2

当有三个或以上的项目时,我们无法将引用的项目DLL包含在其中。

例如,当项目Library1引用项目ReferenceLibrary时,ReferenceLibrary.dll将添加到Library1的引用中。但是,当您将项目Library1引用到测试应用程序项目时,只会将Library1.dll添加到测试应用程序项目的引用中。被引用的项目DLL“Referencelibrary”将被省略。更多详细信息请参见灵活的项目间引用

如果您想将ReferenceLibrary的DLL嵌入到Library1的NuGet包中,并将其引用到测试应用程序项目中,您可以在添加Library1项目引用后,将ReferenceLibrary项目引用添加到测试应用程序项目中,或者将ReferenceLibrary.dll设置为Library1项目的依赖项,您可以将以下条目添加到Library1.csproj,然后通过NuGet打包Library1并安装此包到测试应用程序:

  <ItemGroup>
    <Reference Include="ReferenceLibrary, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
      <HintPath>..\packages\ReferenceLibrary.1.0.0\lib\net461\ReferenceLibrary.dll</HintPath>
      <Private>True</Private>
    </Reference>
  </ItemGroup>

更新:

如果我们想将ReferenceLibrary的DLL嵌入到Library1的Nuget包中,我们需要确保在打包Library1包时,ReferenceLibrary.dll被包含在内,无论我们如何嵌入这些DLLS。因此,在打包Library1包时,您可以将ReferenceLibrary.dll作为文件添加到Library1.nuspec,并将目标设置为lib文件夹。下面是我的Library1.nuspec:

<?xml version="1.0"?>
<package >
  <metadata>
    <id>Library1</id>
    <version>1.0.0</version>
    <authors>xxxx</authors>
    <owners>xxxx</owners>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Package description</description>
    <releaseNotes>Summary of changes made in this release of the package.</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>Test</tags>
  </metadata>
     <files>
        <file src="..\Library1\bin\Debug\Referencelibrary.dll" target="\lib\net461" />
        <file src="..\Library1\bin\Debug\Library1.dll" target="\lib\net461" />
     </files>
</package>

请注意:您还需要在Library1.nuspec中包含Library1.dll。


嗨Leo,谢谢回复。我得晚些时候回家后再查看一下。 ;) - Zorthgo
我尝试使用您上面提到的HintPath,但在运行.Net Core控制台应用程序时仍然遇到了相同的System.IO.FileNotFoundException问题。 :( - Zorthgo
@Zorthgo,我已经更新了我的答案,请在你有空的时候检查一下。如果你对此有任何更新,请告诉我。希望这能帮到你。 - Leo Liu
谢谢更新。我回家后会试一下。不过有一个问题。你提到了一个.nuspec文件,在示例中目标设置为“\lib\net461”。我计划创建.Net Standard库。因此,包信息嵌入在.csproj文件中,而不是单独的.nuspec文件中。上述方法是否也适用于新的“dotnet pack”命令?谢谢! - Zorthgo
@Zorthgo,根据这篇文章和我的测试:https://github.com/dotnet/cli/issues/2170,nupsec文件不支持“dotnet pack”。因此,我建议您使用“nuget pack”命令创建.Net Standard库,请参考https://learn.microsoft.com/en-us/nuget/guides/create-net-standard-packages-vs2015了解详细信息。 - Leo Liu

0

这是Neo答案的扩展版本。此外,指示MSBuild将所有pdb符号打包到所选的符号格式中(内置pdb或snupkg)。

<PropertyGroup>
        <TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);CopyProjectReferencesToPackage</TargetsForTfmSpecificBuildOutput>
        <TargetsForTfmSpecificDebugSymbolsInPackage>$(TargetsForTfmSpecificDebugSymbolsInPackage);CopyProjectReferencesSymbolsToPackage</TargetsForTfmSpecificDebugSymbolsInPackage>
    </PropertyGroup>
    <Target Name="CopyProjectReferencesToPackage" DependsOnTargets="ResolveReferences">
        <ItemGroup>
            <BuildOutputInPackage Include="@(ReferenceCopyLocalPaths->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))" />
        </ItemGroup>
    </Target>
    <Target Name="CopyProjectReferencesSymbolsToPackage" DependsOnTargets="ResolveReferences">
        <ItemGroup>
            <SupposedSymbolFiles Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).pdb')"/>
            <TfmSpecificDebugSymbolsFile Include="@(SupposedSymbolFiles)" Condition="Exists('%(Identity)')">
                <TargetFramework>$(TargetFramework)</TargetFramework>
            </TfmSpecificDebugSymbolsFile>
        </ItemGroup>
    </Target>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接