Установите для файлов содержимого значение "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-package
Visual 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
- net45
Если вам требуется разный контент для разных архитектур, то вы можете добавить папки архитектуры в 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 после сборки.
- создать
tools
папка с вашимInstall.ps1
скрипт - построить свой
nugetPackage
- добавить папку инструментов в встроенную
nugetPackage