Include ONLY .xml file of SPECIFIC nuget package in a different folder
We have a project (ProjectAbc) in a solution which is referencing a nuget package (which is our different project [ProjectXyz] from other solution). We use .net core framework and package reference to include nuget package (ProjectXyz) in .csproj file.
<PackageReference Include="ProjectXyz" Version="1.1.2.3" />
When the solution is build locally or in Prod, ProjectXyz.dll and ProjectXyz.xml gets generated in
ProjectAbc/bin/debug(locally) or release(inProd)/netcoreapp3.1
We want Only ProjectXyz.xml of Only ProjectXyz nuget package to get generated in following folder directly
ProjectAbc
I found various articles which directed me to do different things like copying file to output directory after building or using relative path. Though, tried different ways, I keep getting various errors. It may be because I am not aware of the syntax in .csproj file or also may be because I am not sure what I am doing.
What would be best way to copy file in above case or to generate file directly in the required folder?
for my comment response:
Since I am unable to paste the screenshot in my comment for @Perry Qian-MSFT. So pasting it here.
8/20/2020-----package screenshot---------------------------
You could use <package_name>.props
file in nuget project ProjectXyz to copy such file into the project folder of ProjectAbc. You should use <package_id>.props.
1) First, in your ProjectXyz project, create a folder called build
and then add a file called <package_id>.props
, in your side, it is called ProjectXyz.props
.
2) Add these in ProjectXyz.props
file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\content\any\any\**\*.*"/> //file from the ProjectXyz nuget package
</ItemGroup>
<Copy
SourceFiles="@(SourceScripts)"
DestinationFiles="@(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')" //copy into the main ProjectAbc project folder
/>
</Target>
</Project>
3) Unload your ProjectXyz project and add these in ProjectXyz.csproj
file:
<ItemGroup>
<Content Include="bin\Debug\xxx\ProjectXyz.xml(the path of the ProjectXyz.xml)" Pack="true"
PackagePath="content\any\any;contentFiles\any\any\;;">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
4) Then you should pack your new ProjectXyz project.
5) Then you finish packing, you should first clean all nuget caches first.
Then in your ProjectAbc project, you should uninstall the old one and then install the new ProjectXyz nuget package.
After that, you should build ProjectAbc project first and then you will see that xml document from the nuget package is under the project folder of ProjectAbc.
====================================================================
Update 1
ProjectXyz project is net core
or net standard
while ProjectAbc is net core
.
First, to help you understand the issue, instead, I try to pack ProjectXyz.xml
file into other folder in the ProjectXyz.nupkg
.
1) First, change to use these xml content in ProjectXyz.csproj
file:
<ItemGroup>
<Content Include="bin\Debug\netcoreapp3.1\ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="build\ProjectXyz.props" Pack="true" PackagePath="build\$(TargetFramework)"/>
</ItemGroup>
The goal of it is to pack ProjectXyz.xml
file into the folder called XmlFolder
of XmlFolder.nupkg
. And save ProjectXyz.xml
file in the Nuget package.
Make sure that the file exists in the nuget package.
If the file does not exist, I think it is controlled by your git. Or you could put this ProjectXyz.xml
in your project folder.
Try to right-click on your project-->Properties-->Build-->check this:
Just use <Content Include="ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
In our side, the file can be copied into nupkg nuget package so you should make sure that other tools like git will not interface it.
2) Then change to use these in ProjectXyz.props
file:
<Project>
<Target Name="CopyFilesToProject" BeforeTargets="Build">
<Message Text="Copying ProjectXyz.xml to project" />
<ItemGroup>
//ProjectXyz.xml file from the ProjectXyz nuget package
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\XmlFolder\**\*.*"/>
</ItemGroup>
//copy ProjectXyz.xml file into the main ProjectAbc project folder
<Copy
SourceFiles="@(SourceScripts)"
DestinationFiles="@(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
</Target>
</Project>
The goal of it is that when you install this nuget package, it will first run this target to copy the ProjectXyz.xml
file from the nuget package into the main project ProjectAbc.
Note:
When you finishing installing nuget package, first build ProjectAbc project and the file will exists in ProjectAbc project folder.
3) Then right-click ProjectXyz-->Properties-->Pack to pack your project.
When you install the new ProjectXyz, you should first delete all files under
C:\Users\xxx(current user)\.nuget\packages
.
Also, one more question I had is, the ProjectXyz is being referenced in multiple projects like ProjectAbc, Project123. We dont want ProjectXyz.xml file to show up in Project123 but only in ProjectAbc. I guess with above solution, it might show in both of referencing projects.
For this, you only need to add a condition in CopyFilesToProject target like this: $(ProjectXyz_Flag)==true
and then create a property ProjectXyz_Flag
and set its value to true
in ProjectAbc.csproj
file.
When you build ProjectAbc project, it will determine whether to copy the file based on the switch variable you are currently setting.
a) Add a condition called $(ProjectXyz_Flag)
in ProjectXyz.props
file:
Then repack your ProjectXyz project and do several clean steps as I said before.
When you install that package in ProjectAbc project, you should add such such property in ProjectAbc.csproj
file:
<PropertyGroup>
<ProjectXyz_Flag>true</ProjectXyz_Flag>
</PropertyGroup>
Then when you build ProjectAbc project, it will execute the copy target and if you do not define that property, it will not copy that file in ProjectAbc.
And if those projects do not need ProjectXyz.xml
file, you just do not define that switch property in those projects.
====================================================
Update 2
try to use nuget.exe cli to pack your project, you just need a custom nuspec file:
First, download nuget.exe cli and then configure its local path into PATH System Environment Variable. Then, you can call nuget in CMD.
Second, open CMD and cd xxx(project folder path)
, run nuget spec
to generate the nuspec
file and then modify the generated nuspec
file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<!-- ... -->
</metadata>
<files>
<file src="xxx\ProjectXyz.xml" target="XmlFolder" />
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
Third, run nuget pack
to pack this project.
==============================================================
Update 3
Please first clean your nuget caches or just delete all nuget caches under C:\Users\xxx(current user)\.nuget\packages
. Then reinstall your nuget package.
Also, make sure that the xxx.props
name is the same as your nuget package_id
.
If your nuget package calls ProjectXyz
(package_id). Then the props file should be named as ProjectXyz.props
.
Besides, you should set msbuild project build output verbosity
to detailed
under Tools
-->Options
-->Projects and Solutions
-->Build and Run
.
Then, rebuild your ProjectAbc to check whether the target executes.
======================================================
Update 4
You should make sure that when you pack your package project.mnop
, make sure that the project.mnop.props
file has no syntax errors.
For an example, I have incorrectly wrote something like asdczxcx
in the props file, however, since the build action of the props file is Content
or None
, Vs will not automatically analyze its errors and will not show the errors.
And the error shows the same as yours.
So you should delete that Illegal characters. Make sure that project.mnop.props
has no syntax errors. Then repack your project.
After that, first uninstall the old nuget package project.mnop
on the ProjectAbc.
Then, delete the cache project.mnop
folder under C:\Users\xxx(current user)\.nuget\packages
.
Finally, delete bin
and obj
folder of ProjectAbc, install the new version project.mnop
, then rebuild your project ProjectAbc.
=============================================
Update 5
Actually, this should be an easier way. And your inspiration can be done with a more concise Nuget package structure.
You should only change this:
1) change to use ProjectXyz.xml
from the lib folder in your ProjectXyz.props
:
<SourceScripts Include="$(MSBuildThisFileDirectory)..\..\lib\netcoreapp3.1\ProjectXyz.xml"/>
</ItemGroup>
<Copy
SourceFiles="@(SourceScripts)"
DestinationFiles="@(SourceScripts -> '$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"
/>
2) change your xxx.nuspec
file to:
<?xml version="1.0"?>
<package >
<metadata>
........
<copyright>Copyright 2020</copyright>
<tags>Tag1 Tag2</tags>
</metadata>
<files>
<file src="build\ProjectXyz.props" target="build\netcoreapp3.1" />
</files>
</package>
3) then pack your project and then you can get what you want.
Note: SourceScripts
uses the path $(MSBuildThisFileDirectory)
.
$(MSBuildThisFileDirectory)
means the full path where the ProjectXyz.props
file of the nuget package exists.
In your side, the $(MSBuildThisFileDirectory)
means
C:\Users\xxxxx\.nuget\packages\project.mnop\45.0.0\build\netcoreapp3.1
And then use this path to find the file address of ProjectXyz.xml
in the lib folder of the nuget package.