dotnet core nuget包在恢复时复制内容文件

dotnet core nuget package copying content files on restore

所以我觉得我已经走到了尽头,但希望有人比我在这里知道的更多。我有一些 Typescript 文件,尽管这几乎无关紧要,因为我的所有内容文件都遇到了这个问题。

我能够生成一个 nuget,或者更准确地说 dotnet pack,nuget 包,通过在我的 parent 项目:

<ItemGroup>
  <Content Include="Scripts\Utility.ts">
    <Pack>true</Pack>
    <PackagePath>contentFiles\Scripts\;content\Scripts</PackagePath>
  </Content>
</ItemGroup>

我可以浏览生成的 .nupkg 并看到该文件确实已添加到包中的 content\ScriptscontentFiles\Scripts 位置

问题是每当我在我的 'child' 项目中使用这个包时,Typescript 永远不会被复制到 child 项目的任何文件夹中,尽管我可以看到它被提取在 .nuget\packages\parent\... 个文件夹中。

起初我以为是我在parent项目中的初始设置,可能是,但是在尝试了书中所有内容之后,无法将内容文件复制到child 项目。然后我尝试尝试在我的包的 tools 文件夹中使用 Init.ps1 的黑暗路径,虽然无法调试,但它似乎也偶尔 运行 (我完全卸载了并重新安装了软件包,但大多数时候它仍然无法 运行。)这可能是方法,但我不知道为什么我无法将其输出到 Package Manager Console...也许 Init.ps1 还有希望,但我似乎无法弄清楚。最后,我看到了 nuget .targets file 的一些潜力,但我似乎也无法掌握如何将其用于我的目的!我希望得到一些关于如何完成这项工作的反馈。

显然您需要路径中的 any\any (learn more) 以及包含 <PackageCopyToOutput>true</PackageCopyToOutput>,如下所示:

<ItemGroup>
  <Content Include="Scripts\js\Utility.js">
    <Pack>true</Pack>

    <PackagePath>contentFiles\any\any\wwwroot\js\;content\any\any\wwwroot\js\</PackagePath>

    <PackageCopyToOutput>true</PackageCopyToOutput>
  </Content>
</ItemGroup>

在将 .js 文件包含在包中之前,您还需要预编译 TypeScript

但是,这仍然没有在那里创建文件,只是对它的一些奇怪引用。

最后,我们用 .targets 文件让它工作,你可以在这里找到一个工作的 repo:https://github.com/NuGet/Home/issues/6743

发件人: Announcing NuGet 3.1 with Support for Universal Windows Platform

对于在 Nuget v3.1 中使用 project.json 文件的项目,从 Nuget 包导入内容已被弃用。从那时起,project.json 文件已被删除,取而代之的是新的 .csproj 格式。如果您改用 packages.config 文件,从 Nuget 包导入内容应该仍然有效。

还提到了一个事实,即还有其他包管理器可用于交付内容。

在我看来,新世界的答案是创建一个包含 utility.js 的节点模块,然后让 npm 将其交付给您的项目。

可能的解决方法:

我查看了 .targets 来复制文件并使它正常工作,但它在每个构建上都 运行 - 这对您来说可能是问题,也可能不是问题。我不能用它做我想做的事。

在 [PackageId].targets:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <!-- Either do this for all scripts in the Scripts/js folder -->
    <Target Name="CopyScriptsToProject" BeforeTargets="Build">
        <Message Text="Copying scripts to project" />
        <ItemGroup>
            <SourceScripts Include="$(MSBuildThisFileDirectory)..\..\content\Scripts\js\**\*.*"/>
        </ItemGroup>
        <Copy SourceFiles="@(SourceScripts)" DestinationFiles="@(SourceScripts -> '$(MSBuildProjectDirectory)\wwwroot\js\%(RecursiveDir)%(Filename)%(Extension)')" Condition="!Exists('$(MSBuildProjectDirectory)\wwwroot\js\%(RecursiveDir)%(Filename)%(Extension)')" />
    </Target>
    <!-- Or do this for the individual script -->
    <Target Name="CopyUtilityScriptToProject" BeforeTargets="Build">
        <Copy SourceFiles="$(MSBuildThisFileDirectory)..\..\content\Scripts\js\Utility.js" DestinationFiles="$(MSBuildProjectDirectory)\wwwroot\js\Utility.js" Condition="!Exists('$(MSBuildProjectDirectory)\wwwroot\js\Utility.js')" />
    </Target>
</Project>
<!-- Note: condition can be removed from either if you want it to overwrite each build -->

并在 .csproj 文件中(将 [PackageId] 替换为您的包名称):

<Project Sdk="Microsoft.NET.Sdk">
    ... any Globals for source control stuff ...
    <PropertyGroup>
        <TargetFramework>netcoreapp2.0</TargetFramework>
        <Version>7.0.0</Version>
        <PackageId>[PackageId]</PackageId>
    </PropertyGroup>
    ... any PackageReference stuff ...
    <ItemGroup Label="Packaging">
        <Content Include="build\netcoreapp2.0\[PackageId].targets" PackagePath="build\netcoreapp2.0\[PackageId].targets" />
            <!-- Either -->
            <Content Include="Scripts\js\**\*.*" PackagePath="content\Scripts\js;contentFiles\Scripts\js" />
            <!-- or -->
            <Content Include="Scripts\js\Utility.js" PackagePath="content\Scripts\js;contentFiles\Scripts\js" />
        </ItemGroup>
</Project> 

似乎存在一个错误,即当 <PackageId>[PackageId]</PackageId> 未在 .csproj 中明确设置时,构建目标不起作用。虽然这很可能是我的开发环境的问题。

让我走上了正确的轨道,但将内容文件部署到 bin 目录(正如他所指出的)是不够的。我能够通过更改使用项目的 .csproj 文件中的包引用选项来获取要部署的文件,如下所示:

<PackageReference Include="MyNuGetPackage" Version="0.0.0.1">
  <IncludeAssets>all</IncludeAssets>
  <PrivateAssets>analyzers;build</PrivateAssets>
</PackageReference>

似乎 PrivateAssets 的默认值是 contentfiles;analyzers;build (documentation),这不是我们想要的。

来自@PurplePiranha 的简化代码和解释

TL;DR:

Github

上的基本 .NET6 简化示例代码

分步指南

  1. 选择文件

首先我们需要select所有需要进入nuget包的文件。 将此添加到 .csproj:

<Project Sdk="Microsoft.NET.Sdk">
  ...
  <ItemGroup Label="Packaging">
    <Content Include="<Your directory path>\<your file(s)>" />
  </ItemGroup>

允许多行内容。

  1. 写一个目标

制作一个目标文件,将构建之前(或之后)的文件复制到bin目录:

此文件的位置和名称很重要: \build\.targets

现在,通过在 .csproj 中添加内容行来引用它,确保它会被执行:

<Project Sdk="Microsoft.NET.Sdk">
  ...
  <ItemGroup Label="Packaging">
    <Content Include="build\<LibraryPackageName>.targets" PackagePath="build\<LibraryPackageName>.targets" />

    <Content Include="filesToAdd\*.txt">
      <Pack>true</Pack>
    </Content>
  </ItemGroup>

例如:来自github中的代码:

<Project Sdk="Microsoft.NET.Sdk">
  ...
  <ItemGroup Label="Packaging">
    <Content Include="build\PackageToGenerateFile.targets" PackagePath="build\PackageToGenerateFile.targets" />

    <Content Include="filesToAdd/*.txt">
      <Pack>true</Pack>
    </Content>
  </ItemGroup>

注意:通过将文件复制到 bin 目录,这些文件不是版本控制的一部分,但您的包是!

  1. 构建并打包

在 Visual Studio 中,右键单击包名称并 select“打包”。 应该在你的库的 bin 目录中创建一个新的 nuget 包。

  1. 使用nuget包

现在在目标包中安装 nuget 包。

请注意,这些文件位于解决方案资源管理器中,但不在您磁盘上的目录中。他们有一个快捷方式符号。

  1. 构建目标包

检查bin目录。 文件应复制到目标中提到的位置。