问题描述
我们的解决方案中有一个项目 (ProjectAbc),它引用了一个 nuget 包(这是我们与其他解决方案不同的项目 [ProjectXyz]).我们使用 .net 核心框架和包引用将 nuget 包 (ProjectXyz) 包含在 .csproj 文件中.
<PackageReference Include=ProjectXyz"版本=1.1.2.3"/>
在本地或 Prod 中构建解决方案时,会在其中生成 ProjectXyz.dll 和 ProjectXyz.xml
ProjectAbc/bin/debug(locally) 或 release(inProd)/netcoreapp3.1
我们希望 Only ProjectXyz nuget 包的 Only ProjectXyz.xml 直接在以下文件夹中生成
ProjectAbc
我发现各种文章指导我做不同的事情,比如在构建或使用相对路径后将文件复制到输出目录.虽然尝试了不同的方法,但我不断收到各种错误.可能是因为我不知道 .csproj 文件中的语法,也可能是因为我不确定自己在做什么.
在上述情况下复制文件或直接在所需文件夹中生成文件的最佳方法是什么?
对于我的评论回复:
由于我无法在@Perry Qian-MSFT 的评论中粘贴屏幕截图.所以贴在这里.
8/20/2020-----封装截图---------------------------
您可以使用 nuget 项目 ProjectXyz 中的
文件将此类文件复制到ProjectAbc 的项目文件夹.您应该使用
2) 将这些添加到 ProjectXyz.props
文件中:
<项目><目标名称=CopyFilesToProject";BeforeTargets="构建"><消息文本=将 ProjectXyz.xml 复制到项目"/><项目组><SourceScripts Include="$(MSBuildThisFileDirectory)....contentanyany***.*"/>//来自 ProjectXyz nuget 包的文件</项目组><复制SourceFiles=@(SourceScripts)"DestinationFiles="@(SourceScripts ->'$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"//复制到主ProjectAbc项目文件夹/></目标></项目>
3) 卸载您的 ProjectXyz 项目并将其添加到 ProjectXyz.csproj
文件中:
<ItemGroup><Content Include="binDebugxxxProjectXyz.xml(ProjectXyz.xml的路径)"包=真";PackagePath="contentanyany;contentFilesanyany;;"><PackageCopyToOutput>true</PackageCopyToOutput></内容><无包含=buildProjectXyz.props";包=真";PackagePath="build$(TargetFramework)"/></项目组>
4) 然后你应该打包你的新 ProjectXyz 项目.
5) 然后你打包完毕,你应该先
======================================================================
更新 1
ProjectXyz 项目是 net core
或 net standard
而 ProjectAbc 是 net core
.
首先,为了帮助您理解问题,我尝试将 ProjectXyz.xml
文件打包到 ProjectXyz.nupkg
.
1)首先,在ProjectXyz.csproj
文件中改成使用这些xml内容:
<内容包括="binDebug
etcoreapp3.1ProjectXyz.xml"包=真";PackagePath="XmlFolder"><PackageCopyToOutput>true</PackageCopyToOutput></内容><无包含=buildProjectXyz.props";包=真";PackagePath="build$(TargetFramework)"/></项目组>
它的目的是将ProjectXyz.xml
文件打包到XmlFolder.nupkg
XmlFolder文件夹中>.并将 ProjectXyz.xml
文件保存在 Nuget 包中.
确保该文件存在于 nuget 包中.
如果文件不存在,我认为它是由你的 git 控制的.或者你可以把这个 ProjectXyz.xml
放在你的项目文件夹中.
尝试右键单击您的项目-->属性-->构建-->检查:
只需使用 <Content Include="ProjectXyz.xml";包=真";PackagePath="XmlFolder">
在我们这边,该文件可以复制到 nupkg nuget 包中,因此您应该确保其他工具(如 git)不会对其进行接口.
2) 然后在 ProjectXyz.props
文件中改用这些:
<项目><目标名称=CopyFilesToProject";BeforeTargets="构建"><消息文本=将 ProjectXyz.xml 复制到项目"/><项目组>//ProjectXyz nuget 包中的ProjectXyz.xml 文件<SourceScripts Include="$(MSBuildThisFileDirectory)....XmlFolder***.*"/></项目组>//将 ProjectXyz.xml 文件复制到主 ProjectAbc 项目文件夹中<复制SourceFiles=@(SourceScripts)"DestinationFiles="@(SourceScripts ->'$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"/></目标></项目>
它的目标是当你安装这个nuget包的时候,它会先运行这个target把ProjectXyz.xml
文件从nuget包复制到main项目 ProjectAbc.
注意:
安装完nuget包后,首先构建ProjectAbc项目,该文件将存在于ProjectAbc项目文件夹中.
3) 然后右键ProjectXyz-->Properties-->Pack进行打包你的项目.
安装新的ProjectXyz时,应先删除
下的所有文件C:Usersxxx(当前用户).nugetpackages
.
另外,我还有一个问题是,ProjectXyz 正在被引用在 ProjectAbc、Project123 等多个项目中.我们不想要ProjectXyz.xml 文件显示在 Project123 中,但仅显示在 ProjectAbc 中.一世猜测上面的解决方案,它可能会显示在两个引用中项目.
为此,您只需要像这样在 CopyFilesToProject 目标中添加一个条件:$(ProjectXyz_Flag)==true
然后创建一个属性 ProjectXyz_Flag
并设置其值到 ProjectAbc.csproj
文件中的 true
.
当你构建ProjectAbc项目时,它会根据你当前设置的开关变量来决定是否复制文件.
a) 在 ProjectXyz.props
文件中添加一个名为 $(ProjectXyz_Flag)
的条件:
然后重新打包您的 ProjectXyz 项目并按照我之前所说的执行几个干净的步骤.
当您在 ProjectAbc 项目中安装该软件包时,您应该在 ProjectAbc.csproj
文件中添加此类属性:
<PropertyGroup><ProjectXyz_Flag>true</ProjectXyz_Flag></属性组>
那么当你构建 ProjectAbc 项目时,它会执行复制目标,如果你没有定义该属性,它就不会在 ProjectAbc 中复制那个文件.p>
并且如果这些项目不需要 ProjectXyz.xml
文件,您只需不在这些项目中定义该开关属性即可.
=====================================================
更新 2
尝试使用nuget.exe cli打包你的项目,你只需要一个自定义的 nuspec 文件:
首先,下载nuget.exe cli,然后配置其本地PATH 系统环境变量的路径.然后,你可以在 CMD 中调用 nuget.
第二,打开CMD和cd xxx(项目文件夹路径)
,运行nuget spec
生成nuspec
文件,然后修改生成的nuspec
文件:
<?xml 版本=1.0"?><package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"><元数据><!-- ... --></元数据><文件><文件 src=xxxProjectXyz.xml";目标=XmlFolder";/><file src="buildProjectXyz.props"目标=构建
etcoreapp3.1";/></文件></包>
第三,运行nuget pack
打包这个项目.
===============================================================
更新 3
请先清理您的 nuget 缓存,或者只删除 C:Usersxxx(current user).nugetpackages
下的所有 nuget 缓存.然后重新安装你的 nuget 包.
另外,请确保 xxx.props
名称与您的 nuget package_id
名称相同.
如果您的 nuget 包调用 ProjectXyz
(package_id).那么 props 文件应该命名为 ProjectXyz.props
.
另外,你应该在Tools
-->下将msbuild project build output verbosity
设置为detailed
code>Options-->项目和解决方案
-->构建和运行
.
然后,重建您的 ProjectAbc 以检查目标是否执行.
=======================================================
更新 4
您应该确保在打包您的包project.mnop
时,确保project.mnop.props
文件没有语法错误.
例如,我在 props 文件中错误地写了类似 asdczxcx
的内容,但是,因为 props 文件的 build action 是 Content
或 None
,Vs 不会自动分析其错误,不会显示错误.
并且错误显示与您的相同.
所以你应该删除那些非法字符.确保 project.mnop.props
没有语法错误.然后重新打包你的项目.
之后,先卸载ProjectAbc上旧的nuget包project.mnop
.
然后,删除C:Usersxxx(current user).nugetpackages
下的缓存project.mnop
文件夹.
最后,删除ProjectAbc的bin
和obj
文件夹,安装新版本的project.mnop
,然后重建你的项目ProjectAbc.
==============================================
更新 5
实际上,这应该是一种更简单的方法.您的灵感可以通过更简洁的 Nuget 包结构来完成.
你应该只改变这个:
1) 更改为使用 ProjectXyz.props
中 lib 文件夹中的 ProjectXyz.xml
:
<SourceScripts Include="$(MSBuildThisFileDirectory)....lib
etcoreapp3.1ProjectXyz.xml"/></项目组><复制SourceFiles=@(SourceScripts)"DestinationFiles="@(SourceScripts ->'$(MSBuildProjectDirectory)\%(RecursiveDir)%(Filename)%(Extension)')"/>
2) 将您的 xxx.nuspec
文件更改为:
<?xml 版本=1.0"?><包><元数据>...........<版权>版权 2020</版权><标签>标签1标签2</标签></元数据><文件><file src="buildProjectXyz.props"目标=构建
etcoreapp3.1";/></文件></包>
3)然后打包你的项目,然后你就可以得到你想要的了.
注意:SourceScripts
使用路径$(MSBuildThisFileDirectory)
.
$(MSBuildThisFileDirectory)
表示nuget包的ProjectXyz.props
文件所在的完整路径.
在你这边,$(MSBuildThisFileDirectory)
的意思是
C:Usersxxxxx.nugetpackagesproject.mnop45.0.0uild
etcoreapp3.1
然后用这个路径在nuget包的lib文件夹中找到ProjectXyz.xml
的文件地址.
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)....contentanyany***.*"/> //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="binDebugxxxProjectXyz.xml(the path of the ProjectXyz.xml)" Pack="true"
PackagePath="contentanyany;contentFilesanyany;;">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="buildProjectXyz.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="binDebug
etcoreapp3.1ProjectXyz.xml" Pack="true" PackagePath="XmlFolder">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<None Include="buildProjectXyz.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:Usersxxx(current user).nugetpackages
.
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="xxxProjectXyz.xml" target="XmlFolder" />
<file src="buildProjectXyz.props" target="build
etcoreapp3.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:Usersxxx(current user).nugetpackages
. 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:Usersxxx(current user).nugetpackages
.
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
etcoreapp3.1ProjectXyz.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="buildProjectXyz.props" target="build
etcoreapp3.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:Usersxxxxx.nugetpackagesproject.mnop45.0.0uild
etcoreapp3.1
And then use this path to find the file address of ProjectXyz.xml
in the lib folder of the nuget package.
这篇关于仅在不同文件夹中包含特定 nuget 包的 .xml 文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!