J'essaie de créer un package NuGet pour un assemblage .Net qui se connecte à une DLL win32 native. Je dois emballer à la fois l'assemblage et la dll native avec l'assemblage ajouté aux références du projet (pas de problème à cette partie) et la dll native doit être copiée dans le répertoire de sortie du projet ou dans un autre répertoire relatif.
Mes questions sont:
- Comment emballer la dll native sans que Visual Studio n'essaie de l'ajouter à la liste de références?
- Dois-je écrire un install.ps1 pour copier la DLL native? Si oui, comment puis-je accéder au contenu du package pour le copier?
nuget
nuget-package
nuget-spec
AlonFStackoverflow
la source
la source
Réponses:
L'utilisation de la
Copy
cible dans le fichier de cibles pour copier les bibliothèques requises ne copiera pas ces fichiers dans d'autres projets qui référencent le projet, ce qui entraînera un fichierDllNotFoundException
. Cela peut être fait avec un fichier de cibles beaucoup plus simple, en utilisant unNone
élément, car MSBuild copiera tous lesNone
fichiers pour référencer les projets.Ajoutez le fichier de cibles au
build
répertoire du package nuget avec les bibliothèques natives requises. Le fichier cibles comprendra tous lesdll
fichiers de tous les répertoires enfants dubuild
répertoire. Donc, pour ajouter une versionx86
etx64
d'une bibliothèque native utilisée par unAny CPU
assembly géré, vous vous retrouveriez avec une structure de répertoire similaire à la suivante:Les mêmes répertoires
x86
etx64
seront créés dans le répertoire de sortie du projet lors de la construction. Si vous n'avez pas besoin de sous-répertoires, les**
et les%(RecursiveDir)
peuvent être supprimés et inclure à la place les fichiers requisbuild
directement dans le répertoire. D'autres fichiers de contenu requis peuvent également être ajoutés de la même manière.Les fichiers ajoutés comme
None
dans le fichier cibles ne seront pas affichés dans le projet lorsqu'ils sont ouverts dans Visual Studio. Si vous vous demandez pourquoi je n'utilise pas leContent
dossier dans le nupkg, c'est parce qu'il n'y a aucun moyen de définir l'CopyToOutputDirectory
élément sans utiliser un script PowerShell (qui ne sera exécuté que dans Visual Studio, pas à partir de l'invite de commande, sur les serveurs de build ou dans autres IDE, et n'est pas pris en charge dans les projets project.json / xproj DNX ) et je préfère utiliser unLink
pour les fichiers plutôt que d'avoir une copie supplémentaire des fichiers dans le projet.Mise à jour: Bien que cela devrait également fonctionner avec
Content
plutôt qu'ilNone
ne semble qu'il y ait un bogue dans msbuild, les fichiers ne seront donc pas copiés pour référencer les projets plus d'une étape supprimée (par exemple, proj1 -> proj2 -> proj3, proj3 ne recevra pas les fichiers du package NuGet de proj1 mais proj2 le fera).la source
'$(MSBuildThisFileDirectory)' != '' And HasTrailingSlash('$(MSBuildThisFileDirectory)')
requise? Je pensais que leMSBuildThisFileDirectory
est toujours réglé. Quand ce ne serait pas le cas?**\*.dll
? C'est copier tous les.dll
fichiers dans tous les répertoires. Vous pouvez facilement**\*.*
copier toute une arborescence de répertoires.J'ai récemment eu le même problème lorsque j'ai essayé de créer un package EmguCV NuGet comprenant à la fois des assemblys gérés et des liraires partagés non gérés (qui devaient également être placés dans un
x86
sous - répertoire) qui devaient être copiés automatiquement dans le répertoire de sortie de la construction après chaque build .Voici une solution que j'ai trouvée, qui ne repose que sur NuGet et MSBuild:
Placez les assemblys gérés dans le
/lib
répertoire du package (partie évidente) et les bibliothèques partagées non gérées et les fichiers associés (par exemple les packages .pdb) dans le/build
sous - répertoire (comme décrit dans la documentation NuGet ).Renommez toutes les
*.dll
terminaisons de fichiers non gérées en quelque chose de différent, par exemple*.dl_
pour empêcher NuGet de se plaindre du placement d'assemblys présumés au mauvais endroit ( "Problème: Assemblage en dehors du dossier lib." ).Ajoutez un
<PackageName>.targets
fichier personnalisé dans le/build
sous - répertoire avec quelque chose comme le contenu suivant (voir ci-dessous pour une description):Le
.targets
fichier ci-dessus sera injecté sur une installation du package NuGet dans le fichier de projet cible et est responsable de la copie des bibliothèques natives dans le répertoire de sortie.<AvailableItemName Include="NativeBinary" />
ajoute un nouvel élément "Build Action" pour le projet (qui devient également disponible dans la liste déroulante "Build Action" à l'intérieur de Visual Studio).<NativeBinary Include="...
ajoute les bibliothèques natives placées dans/build/x86
le projet en cours et les rend accessibles à la cible personnalisée qui copie ces fichiers dans le répertoire de sortie.<TargetPath>x86</TargetPath>
ajoute des métadonnées personnalisées aux fichiers et indique à la cible personnalisée de copier les fichiers natifs dans lex86
sous - répertoire du répertoire de sortie réel.Le
<PrepareForRunDependsOn ...
bloc ajoute la cible personnalisée à la liste des cibles dont dépend la construction, consultez le fichier Microsoft.Common.targets pour plus de détails.La cible personnalisée,,
CopyNativeBinaries
contient deux tâches de copie. Le premier est chargé de copier tous les*.dl_
fichiers dans le répertoire de sortie tout en remettant leur extension à l'original*.dll
. Le second copie simplement le reste (par exemple tous les*.pdb
fichiers) au même emplacement. Cela pourrait être remplacé par une tâche de copie unique et un script install.ps1 qui devait renommer tous les*.dl_
fichiers*.dll
pendant l'installation du package.Cependant, cette solution ne copierait toujours pas les binaires natifs dans le répertoire de sortie d'un autre projet référençant celui qui inclut initialement le package NuGet. Vous devez également référencer le package NuGet dans votre projet "final".
la source
DllNotFoundException
renvoyé.<NoWarn>NU5100</NoWarn>
à votre fichier de projetVoici une alternative qui utilise
.targets
pour injecter la DLL native dans le projet avec les propriétés suivantes.Build action
=None
Copy to Output Directory
=Copy if newer
Le principal avantage de cette technique est que la DLL native est copiée
bin/
de manière transitoire dans le dossier des projets dépendants .Voir la mise en page du
.nuspec
fichier:Voici le
.targets
fichier:Cela insère le
MyNativeLib.dll
comme s'il faisait partie du projet d'origine (mais curieusement, le fichier n'est pas visible dans Visual Studio).Notez l'
<Link>
élément qui définit le nom du fichier de destination dans lebin/
dossier.la source
Content
àNone
?Si quelqu'un d'autre tombe sur ça.
Le
.targets
nom de fichier DOIT être égal à l'ID de package NuGetTout le reste ne fonctionnera pas.
Les crédits vont à: https://sushihangover.github.io/nuget-and-msbuild-targets/
J'aurais dû lire plus en détail, comme indiqué ici. Cela m'a pris du temps.
la source
Il est un peu tard mais j'ai créé un package nuget spécialement pour cela.
L'idée est d'avoir un dossier spécial supplémentaire dans votre package nuget. Je suis sûr que vous connaissez déjà Lib et Content. Le package nuget que j'ai créé recherche un dossier nommé Output et copiera tout ce qui s'y trouve dans le dossier de sortie des projets.
La seule chose que vous devez faire est d'ajouter une dépendance nuget au package http://www.nuget.org/packages/Baseclass.Contrib.Nuget.Output/
J'ai écrit un article de blog à ce sujet: http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=6&mobile=0
la source
Il existe une solution pure C # que je trouve plutôt facile à utiliser et je n'ai pas à me soucier des limitations de NuGet. Suivez ces étapes:
Incluez la bibliothèque native dans votre projet et définissez sa propriété Build Action sur
Embedded Resource
.Collez le code suivant dans la classe où vous PInvoke cette bibliothèque.
Appelez cette méthode à partir du constructeur statique comme suit
UnpackNativeLibrary("win32");
et elle décompressera la bibliothèque sur le disque juste avant que vous en ayez besoin. Bien entendu, vous devez vous assurer que vous disposez des autorisations d'écriture sur cette partie du disque.la source
C'est une vieille question, mais j'ai le même problème maintenant, et j'ai trouvé un revirement un peu délicat mais très simple et efficace: créer dans le dossier Contenu standard Nuget la structure suivante avec un sous-dossier pour chaque configuration:
Lorsque vous compressez le fichier nuspec, vous recevrez le message suivant pour chaque bibliothèque native dans les dossiers Debug et Release:
Nous n'avons pas besoin d'une telle "solution" car c'est juste notre objectif: que les bibliothèques natives ne soient pas ajoutées en tant que références aux assemblys NET.
Les avantages sont:
Les inconvénients sont:
la source
Je ne peux pas résoudre votre problème exact, mais je peux vous donner une suggestion.
Votre exigence clé est: "Et ne pas enregistrer automatiquement la référence" .....
Vous devrez donc vous familiariser avec les «éléments de solution»
Voir référence ici:
Ajout d'éléments au niveau de la solution dans un package NuGet
Vous devrez écrire du vaudou PowerShell pour obtenir la copie de votre dll native dans sa maison (encore une fois, parce que vous ne voulez PAS que le vaudou de référence automatique se déclenche)
Voici un fichier ps1 que j'ai écrit ..... pour mettre des fichiers dans un dossier de références tiers.
Il y en a assez pour que vous compreniez comment copier votre dll natif dans une "maison" ... sans avoir à recommencer à zéro.
Encore une fois, ce n'est pas un coup direct, mais c'est mieux que rien.
la source
Mettez c'est le dossier de contenu
la commande le
nuget pack [projfile].csproj
fera automatiquement pour vous si vous marquez les fichiers comme contenu.puis éditez le fichier projet comme mentionné ici en ajoutant l'élément ItemGroup & NativeLibs & None
travaillé pour moi
la source