在nuget包中将内容文件设置为"copy local:always"

Joh*_*ny5 65 copy-local visual-studio nuget nuget-package visual-studio-2012

我在后期构建事件中使用此命令从项目生成nuget包.变量%conf%设置为正确的配置(调试或发布),并且%1是项目名称(例如"MyCompany.MyProject").

nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects
Run Code Online (Sandbox Code Playgroud)

此软件包仅供我们自己使用,永远不会在nuget上发布.它以我们的私有存储库结束.

在项目中,有一个设置为generate action : content和的文件copy local : always.(我的视觉工作室是法语,所以我不是百分之百地确定了它的变形).我们来命名吧importantfile.xml.

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

- content
    - importantfile.xml
- lib
    -net45 (.NetFramework,Version=v4.5)
        -MyCompany.MyProject.dll
Run Code Online (Sandbox Code Playgroud)

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

当我在另一个项目中安装软件包时,importantfile.xml将部署在项目的根目录下.没关系.但事实并非如此copy local : always.

我需要的importantfile.xmlcopy 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>
Run Code Online (Sandbox Code Playgroud)

kjb*_*tel 142

另一种方法是使用与包ID同名的MSBuild目标或props文件,而不是使用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>
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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

  • 这比接受的答案要好得多. (13认同)
  • 我喜欢这个解决方案,并在我的场景中使用它.但是,有一件事需要注意 - 如果您希望用户可能想要修改`importantfile.xml`,那么这个解决方案最适合您 - 该文件仅存在于`packages`文件夹中.但是,如果您不希望用户修改此文件,那么这是一个很好的解决方案:) (4认同)
  • 我无法使用Nuget 2.12.0.817在VS2013中工作,直到我重命名目标文件以匹配包ID.这个命名约定在Nuget 2.5发行说明https://docs.nuget.org/ndocs/release-notes/nuget-2.5中说明. (2认同)

wor*_*yte 38

我知道你们有一个工作的解决方案,但它不适合我,所以我将分享我从NLog.config NuGet包 install.ps1(这里是 github源)中提取的内容.

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

这对我来说似乎更直接,只是希望能帮助那些可能偶然发现这一点的人.

你可以找到公认的国际价值BuildAction的位置和CopyToOutputDirectory所接受的价值在这里.

如果链接再次中断 在此输入图像描述

字段prjBuildActionCompile 1
文件已编译.

prjBuildActionContent 2
该文件包含在Content项目输出组中(请参阅部署应用程序,服务和组件)

prjBuildActionEmbeddedResource 3
该文件作为资源包含在主生成的程序集中或作为附属程序集中.

prjBuildActionNone 0
不采取任何措施.

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
Run Code Online (Sandbox Code Playgroud)


小智 6

我做了这个,它将我的构建文件夹中的文件复制到输出文件夹(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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)


tim*_*use 2

您可以使用PowerShell和Install.ps1NuGet提供的挂钩。

请参阅文档

通过 PowerShell,您必须“搜索”包含您的importantfile.xml属性的内容元素。当脚本找到它时,它必须添加<CopyToOutputDirectory>Always</CopyToOutputDirectory>为子元素。

    <Content Include="importantfile.xml">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
Run Code Online (Sandbox Code Playgroud)

您可以在此处找到一些 PowerShell 片段。只需看一下.ps1文件即可。

您可以尝试以下方法(未测试)。该文件必须命名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)
    }
}
Run Code Online (Sandbox Code Playgroud)

卸载软件包时,您还应该检查所有内容是否已完全删除。

Jonhhy5 的注释

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

  • 请注意,在 V3 中,Install.ps1(和 Uninstall.ps1)支持已被删除。仍然支持 Init.ps1。 (3认同)

归档时间:

查看次数:

30587 次

最近记录:

7 年,1 月 前