Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/283.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用.csproj中的MsBuild和dotnet pack命令将文件从Nuget包复制到输出目录_C#_.net_Msbuild_Nuget_.net Standard - Fatal编程技术网

C# 使用.csproj中的MsBuild和dotnet pack命令将文件从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

上一次,我花了至少6个月的时间才找到如何从Nuget软件包中提取一些文件,但我最终还是找到了

问题是,这个解决方案假设我有一个
.nupkg
文件,并手动添加一个
.targets
文件来执行提取过程

现在情况不同了:

  • 我没有任何
    .nupgk
    文件,我们使用
    dotnetpack
    命令在VSTS服务器上自动生成一个文件。然后,我们从我们的Nuget服务器使用包
  • 我们不能再花6个月的时间来找到解决方案
  • 这是我的
    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>