Установите для файлов содержимого значение "copy local: always" в пакете nuget

Я генерирую пакет nuget из проекта с помощью этой команды в событии после сборки. переменная %conf% установлена ​​правильная конфигурация (отладка или выпуск) и %1 это имя проекта (например, "MyCompany.MyProject").

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

Этот пакет предназначен только для нашего собственного использования, он никогда не будет опубликован на nuget. Это заканчивается в нашем частном хранилище.

В проекте есть файл, который настроен на generate action : content а также copy local : always, (Моя визуальная студия на французском языке, так что я не уверен на 100% в передаче). Давайте назовем это importantfile.xml,

В сгенерированном пакете я получаю следующую структуру:

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

Что хорошо, я хочу importantfile.xml быть развернутым в пакете, потому что, ну, этот файл важен!

Когда я устанавливаю пакет в другом проекте, importantfile.xml развернут в корне проекта. Это нормально. Но это не установлено copy local : always,

я нуждаюсь importantfile.xml быть 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>

5 ответов

Решение

Вы можете использовать PowerShell и Install.ps1 крючок предоставлен NuGet.

Смотрите документацию.

С помощью 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-packageVisual Studio предупреждает, что проект изменен "вне среды". Это вызвано $doc.Save($project.FullName), Если я нажимаю перезагрузить до полного завершения команды, это иногда вызывает ошибки. Хитрость заключается в том, чтобы оставить диалоговое окно там до завершения процесса, а затем перезагрузить проекты.

Вместо использования сценария PowerShell другой подход заключается в использовании целевого файла или файла props 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 каталог вместе с файлом целей.

  • строить
    • importantfile.xml
    • MyPackage.targets
  • Lib
    • net45
      • MyAssembly.dll

Если вам требуется разный контент для разных архитектур, то вы можете добавить папки архитектуры в Build также каждый со своим собственным файлом целей.

Преимущества использования целевого файла по сравнению со скриптом PowerShell с NuGet Content каталог:

  • необходимые файлы содержимого не отображаются в проекте в Visual Studio
  • файлы содержимого связаны, а не копируются в каталог каждого проекта, который ссылается на пакет NuGet (предотвращает наличие нескольких копий и сохраняет поведение, аналогичное для сборок / библиотек из пакетов NuGet)
  • Сценарии PowerShell работают только в Visual Studio и не запускаются, когда NuGet запускается из командной строки (серверы сборки, другие IDE и другие ОС), этот подход будет работать везде
  • Сценарии установки PowerShell не поддерживаются в системе NuGet 3.x project.json.

Я знаю, что у вас, ребята, есть рабочее решение для этого, но оно не сработало для меня, поэтому я собираюсь поделиться тем, что я извлек из пакета NLog.config NuGet install.ps1 (исходный код github здесь).

ПРИМЕЧАНИЕ: это не мой код, это содержимое файла install.ps1 из пакета nuget NLog.config, который просто делится знаниями.

Мне кажется, это немного более прямолинейно и просто в надежде помочь другим, которые могут наткнуться на это.

Вы можете найти принятые значения int для 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

Я сделал это, который копирует файлы из моей папки сборки в выходную папку (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 автоматически добавлять файлы в пакет nuget после сборки.

  1. создать tools папка с вашим Install.ps1 скрипт
  2. построить свой nugetPackage
  3. добавить папку инструментов в встроенную nugetPackage

/questions/30046033/vs2017-ustanovil-dlya-build-action-znachenie-content-v-pakete-nuget/30046056#30046056

Другие вопросы по тегам