67

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

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

这个包仅供我们自己使用,它永远不会在 nuget 上发布。它在我们的私有存储库中结束。

在项目中,有一个文件设置为generate action : contentand copy local : always。(我的 Visual Studio 是法语的,所以我不能 100% 确定翻译)。让我们命名它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重置为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>
4

5 回答 5

163

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

<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与目标文件一起添加到目录中。

  • 建造
    • 重要文件.xml
    • MyPackage.targets
    • 净45
      • MyAssembly.dll

如果您需要不同架构的不同内容,那么您可以在每个架构文件夹下添加Build各自的目标文件。

使用带有 NuGetContent目录的 PowerShell 脚本的目标文件的好处:

  • 所需的内容文件未显示在 Visual Studio 的项目中
  • 内容文件链接到而不是复制到引用 NuGet 包的每个项目的目录中(防止存在多个副本并保持与 NuGet 包中的程序集/库相同的行为)
  • PowerShell 脚本仅在 Visual Studio 中有效,并且在从命令行(构建服务器、其他 IDE 和其他操作系统)运行 NuGet 时不运行,这种方法适用于任何地方
  • NuGet 3.x project.json 系统不支持PowerShell 安装脚本。
于 2015-05-22T01:10:27.347 回答
41

我知道你们有一个可行的解决方案,但它对我不起作用,所以我将分享我从NLog.config NuGet 包install.ps1 中提取的内容(此处为github 源)。

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

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

您可以在此处找到 BuildAction 的可接受 int 值和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
于 2014-09-30T20:34:57.730 回答
7

我做了这个,它将文件从我的构建文件夹复制到输出文件夹(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>

我的项目.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>
于 2017-07-03T07:28:15.610 回答
2

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

请参阅文档

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

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

您可以在此处找到一些 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)
    }
}

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

Jonhhy5的笔记

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

于 2014-01-16T12:14:20.447 回答
0

我编写了一个小工具,称为NuGetLib在构建后自动将文件添加到 nuget 包中。

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

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

于 2017-11-06T10:30:26.803 回答