如何在.NET Core csproj中从引用的NuGet包复制文件到输出目录?

24
我正在尝试在 .NET Core 的 csproj 应用程序中使用 PhantomJS NuGet 包。但我认为,使用新的 PackageReference 语法来引用 NuGet 包是不可能的。
当我像这样引用 PhantomJS 包时:
<PackageReference Include="PhantomJS" Version="2.1.1">
  <IncludeAssets>all</IncludeAssets>
</PackageReference>

当我运行dotnet build时,它什么也没做。

我期望它能将PhantomJS包内的文件复制到输出目录(或项目中的任何位置),以便我可以使用PhantomJS包提供的二进制文件。

是否有另一种方法可以使用MSBuild将PhantomJS NuGet包的内容复制到输出目录?

7个回答

19
有两个解决方案:

1:

  <ItemGroup>
    <PackageReference Include="PhantomJS" Version="1.0.8" GeneratePathProperty="true" />
  </ItemGroup>

  <Target Name="CopyPdfExe" AfterTargets="Build">
    <Copy SourceFiles="$(PkgPhantomJS)\tools\phantomjs\phantomjs.exe" DestinationFolder="$(OutDir)" />
  </Target>

2:
  <ItemGroup>
    <PackageReference Include="PhantomJS" Version="1.0.8" GeneratePathProperty="true" />
  </ItemGroup>

  <ItemGroup>
    <None Include="$(PkgPhantomJS)\tools\phantomjs\phantomjs.exe" CopyToOutputDirectory="PreserveNewest" />
  </ItemGroup>

更倾向于选择#2,因为如果这个项目被其他项目引用,.exe文件也可以复制到输出文件夹中。
参考资料:GeneratePathProperty

谢谢。使用方法#2 - 像魔法一样有效。这使我能够在将csproj迁移到PackageReference后明确修复一个遗留的nuget。我非常感激这种本地和明确的方法。 - mikka
请注意,如果一个 NuGet 包的命名方式符合命名空间的典型方式,使用点号分隔符,比如 "MyPackage.Extensions",那么属性名将会简单地将点号替换为下划线(即 '_')... 所以假设的包示例 "MyPackage.Extensions" 将会被引用为 $(PkgMyPackage_Extensions) - undefined

18
我认为您想要使用:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

在主要的<PropertyGroup>中,所有依赖项都会被复制到输出文件夹中。这意味着每个单独的依赖项都会被复制,因此在某些情况下可能会很混乱。
如果您想要排除特定的程序集或包:
<ItemGroup>
    <-- won't copy to output folder -->
    <PackageReference Include="MahApps.Metro" version="1.6.5">
      <IncludeAssets>compile</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Dragablz" version="0.0.3.203">
      <IncludeAssets>compile</IncludeAssets>
    </PackageReference>
    ... 

    <-- normal will copy to output folder -->
    <PackageReference Include="xmlrpcnet" version="3.0.0.266" />
    <PackageReference Include="YamlDotNet" version="6.0.0" />
</ItemGroup>


<ItemGroup>
    <!-- keep assembly reference from copying to output -->
    <Reference Include="$(SolutionDir)MarkdownMonster\bin\$(Configuration)\$(TargetFramework)\MarkdownMonster.exe">
      <Private>false</Private>
    </Reference> 
</ItemGroup>


在这个上下文中,“compile”表示这些文件可以被编译,但不会被复制到输出文件夹中。

1
我注意到它必须在自己的 PropertyGroup 中,像这样: <PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup> - LosManos
2
不对,@LosManos。如果你有多个组,它们都会聚合成一个单一的组。但顺序可能很重要,所以你可能想把指令移到部分结尾处。 - Rick Strahl

2
在NuGet中,<PackageReference>语法使用传递依赖项,就像project.json语法一样。因此,相同的规则适用。请参阅此NuGet v3,其中讨论了在packages.config和新语法之间的工作原理。具体来说,

您不能依赖于install.ps1或uninstall.ps1运行。这些文件将在使用packages.config时执行,但在v3中将被忽略。因此,您的包需要在不运行它们的情况下可用。Init.ps1仍将在NuGet 3上运行。

要将文件复制到输出目录,PhantomJS NuGet包需要更改为使用contentFiles

1
谢谢。我认为这真的很不幸,我已经提交了一个错误报告。我认为期望所有软件包更改其nuspec并不现实,如果PackageReference有一个功能来复制给定的目录或文件到输出目录,那将更好。我仍会保持这个问题开放,因为在msbuild中有各种技巧可以实现这一点。 - Ciantic
2
有没有人有使用contentFiles的nuspec文件示例? - Jason Rowe
3
这是来自MSBuild存储库的一个例子:https://github.com/Microsoft/msbuild/blob/6851538897f5d7b08024a6d8435bc44be5869e53/build/NuGetPackages/Microsoft.Build.Runtime.nuspec#L30-L32 - Eric Erhardt
1
感谢dotnet build运行时将文件放入bin文件夹,这是一个小进步。 - Jason Rowe

2
标签名称有误导性。尝试使用:

<PackageReference Include="PhantomJS" Version="2.1.1">
  <IncludeAssets>none</IncludeAssets>
</PackageReference>

或者

<PackageReference Include="PhantomJS" Version="2.1.1">
  <ExcludeAssets>all</ExcludeAssets>
</PackageReference>

为了让引用的程序集和其他文件被复制到生成输出中,可以使用包引用。请参见https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files


1

dotnet publish MyProj/MyProj.csproj -c Release -r win-x64 --self-contained -o out - user326608

0

我知道这是一个老问题,但对我有用的是将IncludeAssets设置为“runtime”


0

实际上,在原始问题中声称不起作用的内容在.NET6中对我起作用了:

<PackageReference Include="PhantomJS" Version="2.1.1">
  <IncludeAssets>all</IncludeAssets>
</PackageReference>

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