Je génère un paquet de nuget à partir d'un projet avec cette commande dans l'événement post-build. la variable %conf%
est définie sur la bonne configuration (débogage ou édition) et %1
est le nom du projet (par exemple, "MyCompany.MyProject").
nuget pack -Prop Configuration=%conf% "%1.csproj" -exclude *.sql -IncludeReferencedProjects
Ce paquet est pour notre propre usage seulement, il ne sera jamais publié sur Nuget. Il se termine dans notre référentiel privé.
Dans le projet, un fichier est défini sur generate action : content
et copy local : always
. (Mon studio visuel est en français, je ne suis donc pas sûr à 100% de la traduction). Appelons-le importantfile.xml
.
Dans le paquet généré, je me retrouve avec cette structure:
- content
- importantfile.xml
- lib
-net45 (.NetFramework,Version=v4.5)
-MyCompany.MyProject.dll
Ce qui est bien, je veux que importantfile.xml
soit déployé dans le package, car, eh bien, ce fichier est important!
Lorsque j'installe le package dans un autre projet, importantfile.xml
est déployé à la racine du projet. C'est bon. Mais il n'est pas défini sur copy local : always
.
J'ai besoin de importantfile.xml
pour être copy local : always
dans ce projet où j'installe mon paquet.
Comment puis-je y parvenir?
Notes:
Je peut mettre copy local : always
sur le fichier juste après l'installation du paquet, ce n'est pas grave. Je vivrais avec si les mises à jour ultérieures du paquet laissaient cette propriété telle quelle, ce qui n'est pas le cas. Lors de la mise à jour du paquet, copy local
est réinitialisé sur never
(comme indiqué ici ).
Il y a un fichier nuspec dans le dossier du projet, le voici:
<?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>
Vous pouvez utiliser PowerShell et le hook Install.ps1
fourni par NuGet.
Voir la documentation .
Via PowerShell, vous devez "rechercher" l'élément de contenu qui inclut votre importantfile.xml
dans un attribut. Lorsque le script l'a trouvé, il doit ajouter <CopyToOutputDirectory>Always</CopyToOutputDirectory>
en tant qu'élément enfant.
<Content Include="importantfile.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
Vous pouvez trouver des extraits de PowerShell ici . Jetez un coup d’œil aux fichiers .ps1
.
Vous pouvez essayer ce qui suit (non testé). Le fichier doit être nommé Install.ps1
et copié dans le dossier 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)
}
}
Vous devez également vérifier si tout est complètement supprimé lors de la désinstallation du paquet.
Note de Jonhhy5
Lors de la mise à jour du package via update-package
, Visual Studio avertit que le projet est modifié "en dehors de l'environnement". Cela est causé par $doc.Save($project.FullName)
. Si je clique sur recharger avant la commande est complètement terminée, des erreurs sont parfois générées. L'astuce consiste à laisser la boîte de dialogue jusqu'à la fin du processus et à alors recharger les projets.
Au lieu d'utiliser un script PowerShell, une autre approche consiste à utiliser un fichier cible/props MSBuild portant le même nom que l'ID de package:
<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>
Dans le fichier nuspec, au lieu d’ajouter les fichiers requis au répertoire Content
, ajoutez-les au répertoire Build
avec le fichier cibles.
Si vous avez besoin d'un contenu différent pour différentes architectures, vous pouvez ajouter des dossiers d'architecture sous Build
, chacun avec son propre fichier de cibles.
Avantages de l’utilisation d’un fichier de cibles sur le script PowerShell avec le répertoire NuGet Content
:
Je sais que vous avez une solution qui fonctionne, mais cela ne fonctionne pas pour moi. Je vais donc partager ce que j'ai extrait du paquet NLog.config NuGet install.ps1 (source de github ici ).
NOTE: ce n'est pas mon code, c'est le contenu du fichier install.ps1 de le paquet NLog.config nuget partage simplement les connaissances.
Cela me semble un peu plus simple et j'espère juste aider les autres qui risquent de tomber sur cela.
Vous pouvez trouver les valeurs int acceptées pour BuildAction ici et les valeurs acceptées pour CopyToOutputDirectory here .
Champs PrjBuildActionCompile 1
Le fichier est compilé.
prjBuildActionContent 2
Le fichier est inclus dans le groupe de sortie du projet Contenu (voir Déploiement d'applications, de services et de composants).
prjBuildActionEmbeddedResource 3
Le fichier est inclus dans l’Assemblée générée principale ou dans une Assemblée satellite en tant que ressource.
prjBuildActionNone 0
Aucune action n'est entreprise.
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
J'ai fait ceci qui copie les fichiers de mon dossier de construction dans le dossier de sortie (bin/debug ou bin/release). Fonctionne comme un charme pour moi.
Fichier 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>
J'ai écrit un petit outil appelé NuGetLib
pour ajouter automatiquement des fichiers au paquet Nuget après la construction.
tools
avec votre script Install.ps1
nugetPackage
nugetPackage
construite