C# 使用.csproj中的MsBuild和dotnet pack命令将文件从Nuget包复制到输出目录
上一次,我花了至少6个月的时间才找到如何从Nuget软件包中提取一些文件,但我最终还是找到了 问题是,这个解决方案假设我有一个C# 使用.csproj中的MsBuild和dotnet pack命令将文件从Nuget包复制到输出目录,c#,.net,msbuild,nuget,.net-standard,C#,.net,Msbuild,Nuget,.net Standard,上一次,我花了至少6个月的时间才找到如何从Nuget软件包中提取一些文件,但我最终还是找到了 问题是,这个解决方案假设我有一个.nupkg文件,并手动添加一个.targets文件来执行提取过程 现在情况不同了: 我没有任何.nupgk文件,我们使用dotnetpack命令在VSTS服务器上自动生成一个文件。然后,我们从我们的Nuget服务器使用包 我们不能再花6个月的时间来找到解决方案 这是我的ProjectName.csproj <Project Sdk="Microsoft.NET.S
.nupkg
文件,并手动添加一个.targets
文件来执行提取过程
现在情况不同了:
.nupgk
文件,我们使用dotnetpack
命令在VSTS服务器上自动生成一个文件。然后,我们从我们的Nuget服务器使用包ProjectName.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<Authors>Jérôme MEVEL</Authors>
<Version>1.0.3</Version>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<!-- This answer got many votes on a Github thread so I tried just in case -->
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<!-- Just trying that too-->
<IncludeBuildOutput>true</IncludeBuildOutput>
<IncludeContentInPack>true</IncludeContentInPack>
<!-- I wanted to see the full generated Nuget package -->
<IncludeSource>true</IncludeSource>
<!-- desperate attempt -->
<TargetsForTfmSpecificBuildOutput>GetMyPackageFiles</TargetsForTfmSpecificBuildOutput>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="1.50.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.1" />
<PackageReference Include="NLog" Version="4.5.8">
<!-- Let's try this too just in case-->
<IncludeAssets>all</IncludeAssets>
</PackageReference>
<PackageReference Include="NLog.Extensions.Logging" Version="1.2.1">
<IncludeAssets>all</IncludeAssets>
</PackageReference>
<PackageReference Include="NLog.Web.AspNetCore" Version="4.6.0">
<IncludeAssets>all</IncludeAssets>
</PackageReference>
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.5.1" />
</ItemGroup>
<ItemGroup>
<!-- Added the file to the root folder in case <IncludeAssets>all</IncludeAssets> is looking there -->
<Content Include="NLog.config">
<Pack>true</Pack>
<PackagePath>NLog;;</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<!-- My desired path to look for the file -->
<Content Include="NLog\NLog.config">
<Pack>true</Pack>
<PackagePath>NLog;;</PackagePath>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<!-- This is the default setting, perfectly working when I reference the project instead of installing the Nuget package -->
<ItemGroup>
<None Update="NLog\NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<!-- desperate attempt -->
<Target Name="GetMyPackageFiles">
<ItemGroup>
<BuildOutputInPackage Include="NLog/Nlog.config">
<TargetPath>NLog</TargetPath>
</BuildOutputInPackage>
</ItemGroup>
</Target>
</Project>
netstandard2.0
包装参考
在我的不同尝试中,根据我设置的配置,我最终能够在src/ProjectName.Logging/NLog/NLog.config
或甚至在lib/netstandard2.0/NLog.config
中找到NLog.config
文件
因此,我的文件肯定包含在我的Nuget包文件中,但不会复制到使用该包的项目的输出目录中
在使用类似dotnet pack
的工具生成包时,我试图指定.nuspec
文件,但始终无法获得所需的结果(Nuget包中只包含了我的NLog.config
,或者所有源文件)。此外,这有几个缺点,比如覆盖.csproj
文件中的配置或增加无用的复杂性。我相信我想要实现的目标不需要使用.nuspec
文件就可以实现(也许我错了)
我注意到包中缺少build/ProjectName.targets
文件,这可能就是缺少的部分。那么,如何在不手动修改包的情况下添加此.targets
文件呢
是否有其他方法将我的配置文件从Nuget包复制到输出目录
我真的希望有人能帮我解决这个问题。这是我第二次想执行相同的操作,但有一点不同,再次这是很难做到的
非常感谢好的,我终于找到了解决方案,其中包括一个.nuspec
文件和一个.targets
文件
ProjectName.csproj
只需要包含以下内容
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<NuspecFile>ProjectName.Logging.nuspec</NuspecFile>
</PropertyGroup>
<!-- This is just for some projects referencing this project directly instead of the Nuget package -->
<ItemGroup>
<Content Include="NLog\NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Dapper" Version="1.50.5" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.1.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="2.1.1" />
<PackageReference Include="NLog" Version="4.5.8" />
<PackageReference Include="NLog.Extensions.Logging" Version="1.2.1" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.6.0" />
<PackageReference Include="System.Data.Common" Version="4.3.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.5.1" />
</ItemGroup>
</Project>
最后是ProjectName.targets
小心!该文件位于计算机的Nuget缓存中。您将能够在Visual Studio中的项目根目录中看到它,但不能在Windows资源管理器中看到它(至少在Windows中)。因此,如果您在Visual Studio中修改该文件,它将为此计算机上引用相同Nuget包(和相同版本)的所有其他项目修改该文件
保存最新
我使用dotnet-pack
Nuget-pack
命令生成Nuget包(现在我有了更多的经验,我知道dotnet-pack
不能很好地处理.nuspec
文件,有几个bug)
结果如下:
最后,我可以安装我的软件包,在构建过程中,Nlog.config
文件将从Nuget缓存复制到我的项目的输出目录。如果按照所述从.csproj
文件创建Nuget,则可以在不使用.nuspec
文件的情况下复制文件
要将文件从nuget复制到输出目录,请创建一个包含以下内容的ProjectName.targets
文件:
<ItemGroup>
<LogFiles Include="$(MSBuildThisFileDirectory)\..\contentFiles\LogFiles\*.config" />
</ItemGroup>
<Target Name="CopyLogFiles" BeforeTargets="Build">
<Copy SourceFiles="@(LogFiles)" DestinationFolder="$(TargetDir)CopiedLogFiles\" />
</Target>
当然,路径和名称可以自由选择
这会将所有.config
文件复制到输出目录中名为CopiedLogFiles
的文件夹中 我认为这为这个问题提供了一个更好的答案。
您可以在.csproj中将PackageCopyToOutput
设置为true,以将nuget内容文件声明为“CopyToOutput=true”。这样,任何引用nuget的项目都会在引用的csproj文件中将内容文件标记为true
,指示msbuild将内容文件复制到输出目录:
在nuget项目的.csproj中:
<Content Include="...">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
真的
谢谢您的回答。我刚刚对它进行了测试,它在dotnetpack
和PackageReference
以及Packages.config
中都运行良好。与我的解决方案略有不同:您的方式不会在Visual Studio的解决方案浏览器中创建符号链接,这在我看来不是一件坏事。我接受这个答案,因为我认为它比我的解决方案更好。在我看来,使用新的PackageReference
时,最好不要在VisualStudioExplorer中显示任何指向物理上位于Nuget缓存中的文件的符号链接。否则,在Visual Studio中对此文件所做的任何更改也会更改计算机上引用相同Nuget包和相同版本的任何其他项目的文件,这很可能不是开发人员在创建此目标文件时希望选择的预期行为模板/项类型?(就像在project中,我右键单击Add->NewItem,然后选择什么)我认为目标文件没有模板!它们是常见的xml文件。下面是一些例子。这很有效,谢谢!
<ItemGroup>
<LogFiles Include="$(MSBuildThisFileDirectory)\..\contentFiles\LogFiles\*.config" />
</ItemGroup>
<Target Name="CopyLogFiles" BeforeTargets="Build">
<Copy SourceFiles="@(LogFiles)" DestinationFolder="$(TargetDir)CopiedLogFiles\" />
</Target>
<ItemGroup Label="FilesToCopy">
<Content Include="ProjectName.targets" PackagePath="build/ProjectName.targets" />
<Content Include="LogFiles\*.config" Pack="true" PackagePath="contentFiles\LogFiles">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
</ItemGroup>
<Content Include="...">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>