将内容文件设置为nuget包中的“copy local:always”

我在生成后事件中使用此命令从项目生成nuget包。 variables%conf%被设置为正确的configuration(debugging或释放), %1是项目名称(例如“MyCompany.MyProject”)。

 nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects 

这个软件包仅供我们自己使用,不会在nuget上发布。 它结束于我们的私人存储库。

在项目中,有一个文件设置为generate action : contentcopy local : always 。 (我的视觉工作室是法语的,所以我不是百分百肯定的传播)。 我们把它命名为importantfile.xml

在生成的包中,我最终得到这个结构:

 - content - importantfile.xml - lib -net45 (.NetFramework,Version=v4.5) -MyCompany.MyProject.dll 

这很好,我希望在包中部署importantfile.xml ,因为这个文件很重要!

当我在另一个项目中安装软件包时, importantfile.xml部署在项目的根目录下。 没关系。 但是它并没有设置为copy local : always

我需要importantfile.xmlcopy local : always在我安装我的包的这个项目。

我怎样才能做到这一点?

备注:

可以设置copy local : always安装包后, copy local : always在文件上,这没什么大不了的。 如果后来更新的软件包会让这个属性成为现实,我会忍受它,但事实并非如此。 更新软件包时, copy local被重置为never (如此处所述)。

项目文件夹中有一个nuspec文件,在这里是:

 <?xml version="1.0"?> <package > <metadata> <id>$id$</id> <version>$version$</version> <title>$title$</title> <authors>$author$</authors> <owners>$author$</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>$description$</description> <copyright>Copyright 2014</copyright> <tags>some random tags</tags> </metadata> </package> 

您可以使用PowerShell和NuGet提供的Install.ps1钩子。

请参阅文档 。

通过PowerShell,您必须“search”包含您的importantfile.xml的内容元素。 当脚本find它时,它必须添加<CopyToOutputDirectory>Always</CopyToOutputDirectory>作为子元素。

  <Content Include="importantfile.xml"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> 

你可以在这里find一些PowerShell片段。 只要看看.ps1文件。

你可以尝试以下(未经testing)。 该文件必须命名为Install.ps1并复制到tools文件夹中:

 param($installPath, $toolsPath, $package, $project) # Load project XML. $doc = New-Object System.Xml.XmlDocument $doc.Load($project.FullName) $namespace = 'http://schemas.microsoft.com/developer/msbuild/2003' # Find the node containing the file. The tag "Content" may be replace by "None" depending of the case, check your .csproj file. $xmlNode = Select-Xml "//msb:Project/msb:ItemGroup/msb:Content[@Include='importantfile.xml']" $doc -Namespace @{msb = $namespace} #check if the node exists. if($xmlNode -ne $null) { $nodeName = "CopyToOutputDirectory" #Check if the property already exists, just in case. $property = $xmlNode.Node.SelectSingleNode($nodeName) if($property -eq $null) { $property = $doc.CreateElement($nodeName, $namespace) $property.AppendChild($doc.CreateTextNode("Always")) $xmlNode.Node.AppendChild($property) # Save changes. $doc.Save($project.FullName) } } 

卸载软件包时,还应该检查是否全部删除了。

Jonhhy5的注意

当通过update-package ,Visual Studio会警告说该项目在“环境之外”被修改。 这是由$doc.Save($project.FullName)引起的。 如果在命令完全终止之前单击重新加载,则有时会导致错误。 诀窍是将对话留在那里,直到过程完成, 然后重新加载项目。

另一种方法是使用与包ID相同名称的MSBuild目标或道具文件 ,而不是使用PowerShell脚本:

 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <None Include="$(MSBuildThisFileDirectory)importantfile.xml"> <Link>importantfile.xml</Link> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> </Project> 

然后,在nuspec文件中,不是将所需的文件添加到Content目录,而是将它们与目标文件一起添加到Build目录中。

  • build立
    • importantfile.xml
    • MyPackage.targets
  • LIB
    • net45
      • MyAssembly.dll程序

如果您需要针对不同体系结构的不同内容,则可以在Build下添加架构文件夹,每个文件夹都有自己的目标文件。

使用NuGet Content目录在PowerShell脚本上使用目标文件的好处:

  • 所需的内容文件不在Visual Studio中的项目中显示
  • 内容文件链接到而不是复制到引用NuGet包的每个项目的目录(防止有多个副本并保持与NuGet包的程序集/库相同的行为)
  • PowerShell脚本只能在Visual Studio 中运行,并且在从命令行 (构build服务器,其他IDE和其他操作系统) 运行NuGet时不会运行 ,这种方法无处不在
  • NuGet 3.x project.json系统不支持 PowerShell安装脚本。

所以我知道你们有一个工作的解决scheme,但它并没有为我工作,所以我要分享我从NLog.config NuGet包 install.ps1

注意:这不是我的代码,这是来自NLog.config nuget包的install.ps1的内容,只是共享知识。

似乎对我来说更加直截了当,只是希望帮助那些可能会偶然发现的人。

您可以在这里find可接受的BuildAction的 int值,以及CopyToOutputDirectory的接受值。

 param($installPath, $toolsPath, $package, $project) $configItem = $project.ProjectItems.Item("NLog.config") # set 'Copy To Output Directory' to 'Copy if newer' $copyToOutput = $configItem.Properties.Item("CopyToOutputDirectory") # Copy Always Always copyToOutput.Value = 1 # Copy if Newer copyToOutput.Value = 2 $copyToOutput.Value = 2 # set 'Build Action' to 'Content' $buildAction = $configItem.Properties.Item("BuildAction") $buildAction.Value = 2 

我已经做了这从我的生成文件夹复制文件到输出文件夹(bin / debug或bin / release)。 对我来说就像一个魅力。

Nuspec文件:

 <package> <files> <file src="\bin\Release\*.dll" target="lib" /> <file src="\bin\Release\x64\*.dll" target="build\x64" /> <file src="\bin\Release\x86\*.dll" target="build\x86" /> <file src="MyProject.targets" target="build\" /> </files> </package> 

MyProject.targets

 <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" /> <None Include="@(NativeLibs)"> <Link>%(RecursiveDir)%(FileName)%(Extension)</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project> 

我写了一个名为NuGetLib的小工具,在构build完成后自动将文件添加到nuget包中。

  1. 用你的Install.ps1脚本创build一个tools文件夹
  2. build立你的nugetPackage
  3. 将工具文件夹添加到构build的nugetPackage

https://stackoverflow.com/a/47134733/6229375