Mit diesem Befehl generiere ich im Post-Build-Ereignis ein Nuget-Paket aus einem Projekt. Die Variable %conf%
ist auf die richtige Konfiguration (Debug oder Release) eingestellt, und %1
ist der Projektname (z. B. "MyCompany.MyProject").
nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects
Dieses Paket ist nur für unseren eigenen Gebrauch bestimmt und wird niemals auf Nuget veröffentlicht. Es endet in unserem privaten Repository.
In dem Projekt befindet sich eine Datei, die auf generate action : content
und copy local : always
festgelegt ist. (Mein visuelles Studio ist auf Französisch, daher bin ich mir der Übersetzung nicht 100% sicher). Nennen wir es importantfile.xml
.
Im generierten Paket erhalte ich folgende Struktur:
- content
- importantfile.xml
- lib
-net45 (.NetFramework,Version=v4.5)
-MyCompany.MyProject.dll
Was in Ordnung ist, ich möchte, dass importantfile.xml
im Paket bereitgestellt wird, denn nun, diese Datei ist wichtig!
Wenn ich das Paket in einem anderen Projekt installiere, wird importantfile.xml
im Stammverzeichnis des Projekts bereitgestellt. Kein Problem. Es ist jedoch nicht auf copy local : always
gesetzt.
In diesem Projekt, in dem ich mein Paket installiere, muss importantfile.xml
copy local : always
sein.
Wie kann ich das erreichen?
Anmerkungen:
Ich kann setze copy local : always
auf die Datei kurz nach der Installation des Pakets, das ist keine große Sache. Ich würde damit leben, wenn spätere Aktualisierungen des Pakets diese Eigenschaft unverändert lassen würden, was nicht der Fall ist. Beim Aktualisieren des Pakets wird copy local
auf never
zurückgesetzt (wie angegeben hier ).
Es gibt eine Nuspec-Datei im Projektordner, hier ist es:
<?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>
Sie können PowerShell und den von NuGet bereitgestellten Install.ps1
-Hook verwenden.
Siehe die Dokumentation .
Über PowerShell müssen Sie nach dem Inhaltselement suchen, das Ihren importantfile.xml
in einem Attribut enthält. Wenn das Skript es gefunden hat, muss es <CopyToOutputDirectory>Always</CopyToOutputDirectory>
als untergeordnetes Element hinzugefügt werden.
<Content Include="importantfile.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Sie finden einige PowerShell-Snippets hier . Schauen Sie sich einfach die .ps1
-Dateien an.
Sie könnten Folgendes versuchen (nicht getestet). Die Datei muss Install.ps1
heißen und in den tools
-Ordner kopiert werden:
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)
}
}
Sie sollten auch überprüfen, ob alles vollständig entfernt wurde, wenn Sie das Paket deinstallieren.
Anmerkung von Jonhhy5
Beim Aktualisieren des Pakets über update-package
warnt Visual Studio, dass das Projekt "außerhalb der Umgebung" geändert wird. Das wird durch $doc.Save($project.FullName)
verursacht. Wenn ich auf vor laden klicke, wird der Befehl vollständig abgebrochen, was manchmal zu Fehlern führt. Der Trick besteht darin, den Dialog dort zu belassen, bis der Prozess abgeschlossen ist, und dann die Projekte neu zu laden.
Anstatt ein PowerShell-Skript zu verwenden, besteht ein anderer Ansatz darin, eine MSBuild-Ziele oder eine Requis-Datei mit demselben Namen wie die Paket-ID zu verwenden:
<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>
Fügen Sie dann in der Datei nuspec die erforderlichen Dateien nicht dem Verzeichnis Content
hinzu, sondern fügen Sie sie zusammen mit der Zieldatei dem Verzeichnis Build
hinzu.
Wenn Sie unterschiedliche Inhalte für unterschiedliche Architekturen benötigen, können Sie unter Build
auch Architekturordner mit jeweils einer eigenen Zieldatei hinzufügen.
Vorteile der Verwendung einer Zieldatei über das PowerShell-Skript mit dem NuGet-Verzeichnis Content
:
Ich weiß, ihr habt eine funktionierende Lösung dafür, aber es hat für mich nicht funktioniert, also werde ich mitteilen, was ich aus dem NLog.config-Paket NuGet install.ps1 (github source here ).
HINWEIS: Dies ist nicht mein Code, sondern der Inhalt der install.ps1 von Das NLog.config-Nuget-Paket teilt nur das Wissen.
Es scheint mir etwas geradliniger zu sein und zu hoffen, anderen zu helfen, die wahrscheinlich darüber stolpern werden.
Die akzeptierten int-Werte für BuildAction finden Sie hier und die akzeptierten Werte für CopyToOutputDirectory hier .
Felder PrjBuildActionCompile 1
.__ Die Datei wird kompiliert.
prjBuildActionContent 2
Die Datei ist in der Content-Projektausgabegruppe enthalten (siehe Bereitstellen von Anwendungen, Services und Komponenten).
prjBuildActionEmbeddedResource 3
Die Datei ist in der generierten Assembly oder in einer Satellitenassembly als Ressource enthalten.
prjBuildActionNone 0
Es wird nichts unternommen.
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
Ich habe dies gemacht, das Dateien aus meinem Build-Ordner in den Ausgabeordner kopiert (bin/debug oder bin/release). Funktioniert für mich wie ein Zauber.
Nuspec-Datei:
<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>
MeineProjekt.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>
Ich habe ein kleines Tool namens NuGetLib
geschrieben, um nach dem Build automatisch Dateien zum Nuget-Paket hinzuzufügen.
tools
-Ordner mit Ihrem Install.ps1
-SkriptnugetPackage
nugetPackage
hinzu.