<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>
As you can see I tried several different settings. This MsBuild results in a NLog.config
file included in a NLog
folder at the root of the Nuget package file.
During my different tries, depending of the configuration I set, I was able to end-up with the NLog.config
file at src/ProjectName.Logging/NLog/NLog.config
or even at lib/netstandard2.0/Nlog.config
.
So my file is definitely included in my Nuget package file but isn't copied in the output directory of the project that consumes the package.
I tried to specify a .nuspec
file when generating my package with dotnet pack
like described here but I was never able to get a desired result (either only my NLog.config
was included in the Nuget package or all the source files). Moreover, this has several downsides like overriding the configuration in the .csproj
file or adding useless complexity. I believe what I want to achieve could be done without using a .nuspec
file (maybe I'm wrong).
I noticed the build/ProjectName.targets
file is missing in my package and this is probably the missing piece. So how to add this .targets
file without manually modifying the package?
Is there another way to copy my config file out of the Nuget package to the output directory?
I really hope someone could help me solve this issue. This is the 2nd time I want to perform the same operation but with a slight difference and once again this is hard to do.
Thanks a lot
It is possible to copy files without the .nuspec
file, if you create your nuget from the .csproj
file as described here.
And to copy files from nuget to output directory, create a ProjectName.targets
file with the following content:
<ItemGroup>
<LogFiles Include="$(MSBuildThisFileDirectory)\..\contentFiles\LogFiles\*.config" />
</ItemGroup>
<Target Name="CopyLogFiles" BeforeTargets="Build">
<Copy SourceFiles="@(LogFiles)" DestinationFolder="$(TargetDir)CopiedLogFiles\" />
</Target>
In your .csproj
file add:
<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>
The paths and names can of course be freely chosen.
This should copy all .config
files to a folder called CopiedLogFiles
in the output directory!
–
–
–
–
Ok I finally found the solution and that includes a .nuspec
file and a .targets
file as well.
The ProjectName.csproj
just needs to include this
<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>
In the ProjectName.nuspec
you put everything related to the Nuget package
<?xml version="1.0"?>
<package >
<metadata>
<id>ProjectName.Logging</id>
<version>1.1.0</version>
<authors>Jérôme MEVEL</authors>
<description>Just a logging component</description>
<releaseNotes>Extract the NLog.config file automatically</releaseNotes>
<dependencies>
<dependency id="Dapper" version="1.50.5" />
<dependency id="Microsoft.Extensions.DependencyInjection" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" />
<dependency id="NLog" version="4.5.8" />
<dependency id="NLog.Extensions.Logging" version="1.2.1" />
<dependency id="NLog.Web.AspNetCore" version="4.6.0" />
<dependency id="System.Data.Common" version="4.3.0" />
<dependency id="System.Data.SqlClient" version="4.5.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\netstandard2.0\ProjectName.Logging.dll" target="lib/netstandard2.0/ProjectName.Logging.dll" />
<file src="ProjectName.Logging.targets" target="build/ProjectName.Logging.targets" />
<file src="NLog/Nlog.config" target="content/Nlog.config" />
</files>
</package>
And finally the ProjectName.targets
. Careful! The file is located in the Nuget cache of the machine. You will be able to see it at the root of your project in Visual Studio but not in the Windows Explorer (in Windows at least). So if you modify the file in Visual Studio, it will modify it for ALL other projects on this machine referencing the same Nuget package (and same version).
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Content Include="$(MSBuildThisFileDirectory)\..\content/NLog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>
I generate the Nuget package using the dotnet pack
nuget pack
command (now that I've more experience I know that dotnet pack
doesn't work well with a .nuspec
file, there are several bugs)
Here is the result:
Finally I can just install my package and during the build process, the Nlog.config
file will be copied out of the Nuget cache to the output directory of my project.
I think that How do you set nuget contentFiles CopyToOutput value to true when using a .Net Standard library .csproj? provides a better answer to this question.
https://github.com/NuGet/NuGet.Client/pull/1450
You can set PackageCopyToOutput
to true in the .csproj to declare the nuget content file as "CopyToOutput=true". That way any project referencing the nuget will have the content file marked with <CopyToOutput>true</CopyToOutput>
in the referring csproj file, instructing msbuild to copy the content file to the ouput directory:
In the .csproj of the nuget project:
<Content Include="...">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.