J'ai quatre projets dans ma solution Visual Studio (tout le monde cible .NET 3.5) - pour mon problème, seuls ces deux sont importants:
- MyBaseProject <- cette bibliothèque de classes fait référence à un fichier DLL tiers (elmah.dll)
- MyWebProject1 <- ce projet d'application Web a une référence à MyBaseProject
J'ai ajouté la référence elmah.dll à MyBaseProject dans Visual studio 2008 en cliquant sur "Ajouter une référence ..." → onglet "Parcourir" → en sélectionnant "elmah.dll".
Les propriétés de la référence Elmah sont les suivantes:
- Alias - global
- Copier local - vrai
- Culture -
- Description - Modules et gestionnaires de journalisation des erreurs (ELMAH) pour ASP.NET
- Type de fichier - Assemblage
- Chemin - D: \ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
- Résolu - Vrai
- Version d'exécution - v2.0.50727
- Version spécifiée - false
- Nom fort - faux
- Version - 1.0.11211.0
Dans MyWebProject1, j'ai ajouté la référence au projet MyBaseProject en: "Ajouter une référence ..." → onglet "Projets" → en sélectionnant "MyBaseProject". Les propriétés de cette référence sont les mêmes, à l'exception des membres suivants:
- La description -
- Chemin - D: \ webs \ CMS \ MyBaseProject \ bin \ Debug \ MyBaseProject.dll
- Version - 1.0.0.0
Si j'exécute la génération dans Visual Studio, le fichier elmah.dll est copié dans le répertoire bin de mon MyWebProject1 , avec MyBaseProject.dll!
Cependant, si je nettoie et exécute MSBuild pour la solution (via D: \ webs \ CMS> C: \ WINDOWS \ Microsoft.NET \ Framework \ v3.5 \ MSBuild.exe / t: ReBuild / p: Configuration = Debug MyProject.sln ) le elmah.dll est manquant dans le répertoire bin de MyWebProject1 - bien que la construction elle-même ne contienne aucun avertissement ou erreur!
J'ai déjà vérifié que le .csproj de MyBaseProject contient l' élément privé avec la valeur "true" (qui devrait être un alias pour " copier local " dans Visual Studio):
<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\mypath\__tools\elmah\Elmah.dll</HintPath>
**<Private>true</Private>**
</Reference>
(La balise privée n'apparaissait pas par défaut dans le xml du .csproj, bien que Visual Studio ait dit "copier local" vrai. J'ai basculé "copier local" sur faux - enregistré - et le redéfinir sur vrai - enregistrer!)
Quel est le problème avec MSBuild? Comment obtenir la référence (elmah.dll) copiée dans le bac de MyWebProject1?
Je ne veux PAS ajouter une action de copie post-construction à la commande post-construction de chaque projet! (Imaginez que de nombreux projets dépendent de MyBaseProject!)
Réponses:
Je ne sais pas pourquoi il est différent lors de la construction entre Visual Studio et MsBuild, mais voici ce que j'ai trouvé lorsque j'ai rencontré ce problème dans MsBuild et Visual Studio.
Explication
Pour un exemple de scénario, supposons que nous ayons le projet X, l'assembly A et l'assembly B. L'assembly A fait référence à l'assembly B, donc le projet X inclut une référence à la fois à A et à B. De plus, le projet X inclut du code qui fait référence à l'assembly A (par exemple A. SomeFunction ()). Maintenant, vous créez un nouveau projet Y qui fait référence au projet X.
Ainsi, la chaîne de dépendance ressemble à ceci: Y => X => A => B
Visual Studio / MSBuild essaie d'être intelligent et n'introduit que des références dans le projet Y qu'il détecte comme étant requises par le projet X; il le fait pour éviter la pollution de référence dans le projet Y. Le problème est, puisque le projet X ne contient pas réellement de code qui utilise explicitement l'assembly B (par exemple B.SomeFunction ()), VS / MSBuild ne détecte pas que B est requis par X, et donc ne le copie pas dans le répertoire bin du projet Y; il copie uniquement les assemblages X et A.
Solution
Vous avez deux options pour résoudre ce problème, les deux entraînant la copie de l'assembly B dans le répertoire bin du projet Y:
Personnellement, je préfère l'option 2 pour quelques raisons.
Voici un exemple du "code factice" que j'ajoute généralement lorsque je rencontre cette situation.
la source
Type dummyType = typeof(AssemblyA.AnyClass);
Console.WriteLine(dummyType.FullName);
enum
de B et j'ai supposé que l'énumération était en ligne. J'ai ajouté du code pour utiliser directement un type de B et cela n'a pas aidé. Il a également toujours été le cas où mon X utilise des types dans A qui sous-types dans B, donc je ne peux pas comprendre comment le compilateur pense que B n'est pas requis par X et peut être ignoré. Ce sont des bonkers.Je le traite comme ça. Accédez aux propriétés de votre référence et procédez comme suit:
et c'est tout.
Visual Studio 2010 ne met pas initialement:
<private>True</private>
dans la balise de référence et la définition de "copier local" sur false provoque la création de la balise. Ensuite, il le réglera sur vrai et faux en conséquence.la source
<Private>true</Private>
mais cela ne semblait avoir aucun effet sur MSBuild. Au final, je viens d'ajouter des références NuGet à des projets de niveau inférieur.Have you tried turning it off and on again?
, et cela a fonctionné!Si vous n'utilisez pas l'assembly directement dans le code, alors Visual Studio, tout en essayant d'être utile, détecte qu'il n'est pas utilisé et ne l'inclut pas dans la sortie. Je ne sais pas pourquoi vous voyez un comportement différent entre Visual Studio et MSBuild. Vous pouvez essayer de définir la sortie de génération sur diagnostic pour les deux et comparer les résultats pour voir où ils divergent.
Quant à votre référence elmah.dll si vous ne la référencez pas directement dans le code, vous pouvez l'ajouter en tant qu'élément à votre projet et définir l'action de génération sur
Content
et le répertoire de copie dans le répertoire de sortie surAlways
.la source
Jeter un coup d'œil à:
Ce fil de discussion MSBuild que j'ai commencé
Vous y trouverez ma solution / solution temporaire!
(MyBaseProject a besoin d'un code qui fait référence à certaines classes (quoi que) de elmah.dll pour qu'elmah.dll soit copié dans le bac de MyWebProject1!)
la source
J'ai eu le même problème.
Vérifiez si la version du framework de votre projet est la même que la version du framework de la DLL que vous mettez en référence.
Dans mon cas, mon client a été compilé à l'aide de "Framework 4 Client" et la DLL était dans "Framework 4".
la source
Le problème auquel j'étais confronté était que j'avais un projet qui dépend d'un projet de bibliothèque. Afin de construire, je suivais ces étapes:
Cela signifiait bien sûr que je manquais les fichiers dll de ma bibliothèque dans le bac et, surtout, dans le fichier zip du package. J'ai trouvé que cela fonctionne parfaitement:
Je n'ai aucune idée pourquoi ce travail ou pourquoi il ne l'a pas fait en premier lieu. Mais j'espère que ça aide.
la source
J'ai juste eu exactement le même problème et cela s'est avéré être dû au fait que 2 projets dans la même solution faisaient référence à une version différente de la bibliothèque tierce.
Une fois que j'ai corrigé toutes les références, tout fonctionnait parfaitement.
la source
Comme Alex Burtsev l'a mentionné dans un commentaire, tout ce qui n'est utilisé que dans un dictionnaire de ressources XAML, ou dans mon cas, tout ce qui n'est utilisé qu'en XAML et pas dans le code derrière, n'est pas considéré comme `` utilisé '' par MSBuild.
Donc, le simple fait de créer une référence factice à une classe / composant dans l'assembly dans un code derrière était suffisant pour convaincre MSBuild que l'assembly était réellement utilisé.
la source
La modification du cadre cible de .NET Framework 4 Client Profile à .NET Framework 4 a résolu ce problème pour moi.
Donc, dans votre exemple: définissez le framework cible sur MyWebProject1 sur .NET Framework 4
la source
En utilisant le schéma de deadlydog,
Y => X => A => B ,
mon problème était quand j'ai construit Y, les assemblys (A et B, tous les 15 d'entre eux) à partir de X n'apparaissaient pas dans le dossier bin de Y.
Je l'ai résolu en supprimant la référence X de Y, en enregistrant, en construisant, puis en rajoutant la référence X (une référence de projet), et en enregistrant, en construisant et A et B ont commencé à apparaître dans le dossier bin de Y.
la source
J'ai eu le même problème et la DLL était une référence chargée dynamiquement. Pour résoudre le problème, j'ai ajouté une "utilisation" avec l'espace de noms de la DLL. Maintenant, la DLL est copiée dans le dossier de sortie.
la source
Cela nécessite d'ajouter un
.targets
fichier à votre projet et de le configurer pour qu'il soit inclus dans la section des inclusions du projet.Voir ma réponse ici pour la procédure.
la source
Référencer des assemblys qui ne sont pas utilisés pendant la génération n'est pas la bonne pratique. Vous devez augmenter votre fichier de construction pour qu'il copie les fichiers supplémentaires. Soit en utilisant un événement post-construction, soit en mettant à jour le groupe de propriétés.
Quelques exemples peuvent être trouvés dans d'autres articles
la source
Un autre scénario où cela apparaît est si vous utilisez l'ancien type de projet «Site Web» dans Visual Studio. Pour ce type de projet, il ne peut pas référencer des fichiers .dll qui se trouvent en dehors de sa propre structure de répertoires (dossier en cours et vers le bas). Donc, dans la réponse ci-dessus, disons que votre structure de répertoire ressemble à ceci:
Où ProjectX et ProjectY sont des répertoires parent / enfant et ProjectX fait référence à A.dll qui à son tour fait référence à B.dll et B.dll est en dehors de la structure de répertoires, comme dans un package Nuget à la racine (Packages), puis A. dll sera inclus, mais B.dll ne le sera pas.
la source
J'ai eu un problème similaire aujourd'hui, et ce n'est certainement pas la réponse à votre question. Mais j'aimerais informer tout le monde et éventuellement fournir une étincelle de perspicacité.
J'ai une application ASP.NET. Le processus de génération est défini pour nettoyer puis générer.
J'ai deux scripts Jenkins CI . Un pour la production et un pour la mise en scène. J'ai déployé mon application sur la mise en scène et tout a bien fonctionné. Déployé en production et il manquait un fichier DLL référencé. Ce fichier DLL était juste à la racine du projet. Pas dans aucun référentiel NuGet. La DLL a été définie sur
do not copy
.Le script CI et l'application étaient les mêmes entre les deux déploiements. Toujours après le nettoyage et le déploiement dans l'environnement de transfert, le fichier DLL a été remplacé à l'emplacement de déploiement de l'application ASP.NET (
bin/
). Ce n'était pas le cas pour l'environnement de production.Il s'avère que dans une branche de test, j'avais ajouté une étape au processus de génération pour copier sur ce fichier DLL dans le
bin
répertoire. Maintenant, la partie qui a pris un peu de temps à comprendre. Le processus CI ne se nettoyait pas lui-même. La DLL a été laissée dans le répertoire de travail et était accidentellement empaquetée avec le fichier ASP.NET .zip. La branche de production n'a jamais copié le fichier DLL de la même manière et ne l'a jamais déployé accidentellement.TLDR; Vérifiez et assurez-vous de savoir ce que fait votre serveur de build.
la source
Assurez-vous que les deux projets sont dans la même version .net vérifiez également la copie de la propriété locale, mais cela devrait être
true
par défautla source
Utilisation de Visual Studio 2015 en ajoutant le paramètre supplémentaire
à la ligne de commande msbuild a résolu le problème.
la source
Je viens de rencontrer un problème très similaire. Lors de la compilation à l'aide de Visual Studio 2010, le fichier DLL était inclus dans le
bin
dossier. Mais lors de la compilation à l'aide de MSBuild, le fichier DLL tiers n'était pas inclus.Très frustrant. La façon dont je l'ai résolu était d'inclure la référence NuGet au package dans mon projet Web même si je ne l'utilise pas directement là-bas.
la source
L'inclusion de tous les fichiers DLL référencés de vos références de projet dans le projet de site Web n'est pas toujours une bonne idée, en particulier lorsque vous utilisez l' injection de dépendance : votre projet Web veut simplement ajouter une référence au fichier / projet DLL d'interface, pas toute DLL d'implémentation concrète fichier.
Parce que si vous ajoutez une référence directement à un fichier / projet DLL d'implémentation, vous ne pouvez pas empêcher votre développeur d'appeler un "nouveau" sur des classes concrètes du fichier / projet DLL d'implémentation plutôt que via l'interface. C'est aussi que vous avez indiqué un "hardcode" dans votre site Web pour utiliser l'implémentation.
la source