Установите файлы содержимого для "копирования локального: всегда" в пакете nuget
Я генерирую пакет nuget из проекта с этой командой в событии post-build. переменная %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>
Ответы
Ответ 1
Вы можете использовать PowerShell и hook Install.ps1
, предоставляемые NuGet.
См. документацию .
Через PowerShell вам нужно "искать" элемент контента, который включает ваш importantfile.xml
в атрибуте. Когда script нашел его, он должен добавить <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)
. Если я нажму на перезагрузку до того, как команда будет полностью завершена, она иногда вызывает ошибки. Хитрость заключается в том, чтобы оставить диалог там до тех пор, пока процесс не завершится, а затем перезагрузите проекты.
Ответ 2
Вместо использования PowerShell script другой подход заключается в использовании целей или реквизитов 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
Если вам требуется различный контент для разных архитектур, вы можете добавить папки архитектуры в Build
также каждый со своим собственным файлом целей.
Преимущества использования файла целей над PowerShell script с каталогом NuGet Content
:
- требуемые файлы содержимого не отображаются в проекте в Visual Studio
- файлы содержимого связаны, а не копируются в каталог каждого проекта, который ссылается на пакет NuGet (предотвращая наличие нескольких копий и сохраняя поведение так же, как для сборок/библиотек из пакетов NuGet).
- Сценарии PowerShell работают только в Visual Studio и не запускаются, когда NuGet запускается из командной строки (серверы сборки, другие IDE и другие ОС), этот подход будет работа везде
- Скрипты установки PowerShell не поддерживаются в системе NuGet 3.x project.json.
Ответ 3
поэтому я знаю, что у вас, ребята, есть рабочее решение, но это не сработало для меня, поэтому я собираюсь поделиться тем, что я вытащил из NLog.config пакет NuGet install.ps1
ПРИМЕЧАНИЕ: это не мой код, это содержимое install.ps1 из пакет NLog.config nuget просто делится знаниями.
кажется немного более прямым для меня и просто надеется помочь другим, которые, скорее всего, наткнутся на это.
вы можете найти принятые значения int для BuildAction здесь и принятые значения для 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
Ответ 4
Я сделал это, который копирует файлы из моей папки сборки в выходную папку (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>
Ответ 5
Я написал небольшой инструмент под названием NuGetLib
для автоматического добавления файлов в пакет nuget после сборки.
- создайте папку
tools
со своим Install.ps1
script
- создайте
nugetPackage
- добавьте папку инструментов в построенный
nugetPackage
fooobar.com/info/76532/...