HintPath vs ReferencePath dans Visual Studio

120

Quelle est exactement la différence entre le HintPathdans un fichier .csproj et le ReferencePathdans un .csproj.userfichier? Nous essayons de nous engager dans une convention où les DLL de dépendance se trouvent dans un repo svn "releases" et tous les projets pointent vers une version particulière. Étant donné que différents développeurs ont des structures de dossiers différentes, les références relatives ne fonctionneront pas, nous avons donc proposé un schéma pour utiliser une variable d'environnement pointant vers le dossier des versions du développeur particulier pour créer une référence absolue. Ainsi, après l'ajout d'une référence, nous éditons manuellement le fichier projet pour changer la référence en un chemin absolu à l'aide de la variable d'environnement.

J'ai remarqué que cela peut être fait à la fois avec le HintPathet le ReferencePath, mais la seule différence que j'ai pu trouver entre eux est que cela HintPathest résolu au moment de la construction et ReferencePathlorsque le projet est chargé dans l'EDI. Je ne sais pas vraiment quelles en sont les ramifications. J'ai remarqué que VS réécrit parfois le .csproj.useret je dois le réécrire ReferencePath, mais je ne suis pas sûr de ce qui le déclenche.

J'ai entendu dire qu'il est préférable de ne pas archiver le .csproj.userfichier car il est spécifique à l'utilisateur, donc j'aimerais viser cela, mais j'ai également entendu dire que la HintPathDLL -spécifiée n'est pas "garantie" d'être chargée si la même DLL se trouve par exemple dans le répertoire de sortie du projet. Des pensées à ce sujet?

four grille-pain
la source

Réponses:

133

Selon ce blog MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Il existe un ordre de recherche pour les assemblages lors de la création. L'ordre de recherche est le suivant:

  • Fichiers du projet en cours - indiqués par $ {CandidateAssemblyFiles}.
  • Propriété $ (ReferencePath) provenant du fichier .user / cibles.
  • Métadonnées% (HintPath) indiquées par l'élément de référence.
  • Répertoire du framework cible.
  • Répertoires trouvés dans le registre qui utilise l'enregistrement AssemblyFoldersEx.
  • Dossiers d'assemblage enregistrés, indiqués par $ {AssemblyFolders}.
  • $ (OutputPath) ou $ (OutDir)
  • GAC

Donc, si l'assembly souhaité est trouvé par HintPath , mais qu'un autre assembly peut être trouvé à l'aide de ReferencePath , il préférera l' assembly ReferencePath 'd à celui de HintPath ' d.

ajs410
la source
2
Sauf qu'ils ont changé cela dans VS2019 - nous utilisons cette configuration depuis des années maintenant. Plus maintenant. Les fichiers de référentiel ont maintenant une priorité plus élevée que les fichiers dll de construction de solution - allez comprendre :(
Christian
@Christian: Que sont les fichiers de référentiel? Avez-vous plus d'informations à ce sujet?
test le
@testing Je parle des chemins de référence externes, vous pouvez définir dans la configuration de votre projet de VS. Malheureusement, ce paramètre important pour l'environnement du projet (nous avons trois environnements différents) ne peut pas être enregistré dans les paramètres du projet; vous devez donc l'ajouter explicitement en tant que paramètre au script de compilation en ligne de commande.
Christian
31

Regardez dans le fichier Microsoft.Common.targets

La réponse à la question se trouve dans le fichier Microsoft.Common.targetsde la version de votre framework cible.

Pour .Net Framework version 4.0 (et 4.5!), L'élément AssemblySearchPaths est défini comme ceci:

    <!--
    The SearchPaths property is set to find assemblies in the following order:

        (1) Files from current project - indicated by {CandidateAssemblyFiles}
        (2) $(ReferencePath) - the reference path property, which comes from the .USER file.
        (3) The hintpath from the referenced item itself, indicated by {HintPathFromItem}.
        (4) The directory of MSBuild's "target" runtime from GetFrameworkPath.
            The "target" runtime folder is the folder of the runtime that MSBuild is a part of.
        (5) Registered assembly folders, indicated by {Registry:*,*,*}
        (6) Legacy registered assembly folders, indicated by {AssemblyFolders}
        (7) Resolve to the GAC.
        (8) Treat the reference's Include as if it were a real file name.
        (9) Look in the application's output folder (like bin\debug)
    -->
<AssemblySearchPaths Condition=" '$(AssemblySearchPaths)' == ''">
  {CandidateAssemblyFiles};
  $(ReferencePath);
  {HintPathFromItem};
  {TargetFrameworkDirectory};
  {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
  {AssemblyFolders};
  {GAC};
  {RawFileName};
  $(OutDir)
</AssemblySearchPaths>

Pour .Net Framework 3.5, la définition est la même, mais le commentaire est erroné. La définition 2.0 est légèrement différente, elle utilise $ (OutputPath) au lieu de $ (OutDir).

Sur ma machine, j'ai les versions suivantes du fichier Microsoft.Common.targets:

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework64\v3.5\Microsoft.Common.targets
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Microsoft.Common.targets

C'est avec Visual Studio 2008, 2010 et 2013 installé sur Windows 7.

Le fait que le répertoire de sortie soit recherché peut être un peu frustrant (comme le souligne l'affiche d'origine) car il peut masquer un HintPath incorrect. La solution se construit correctement sur votre machine locale, mais se rompt lorsque vous construisez dans une structure de dossier propre (par exemple sur la machine de construction).

Nils Lande
la source
J'ai un problème similaire, dans ce cas, où dois-je placer les fichiers dll? Framework ou Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev
5

Ma propre expérience a été qu'il est préférable de s'en tenir à l'un des deux types de références d'assemblage:

  • Un assembly 'local' dans le répertoire de construction actuel
  • Une assemblée au sein du GAC

J'ai trouvé (tout comme vous l'avez décrit) d'autres méthodes qui sont soit trop facilement cassées, soit ont des exigences de maintenance ennuyeuses.

Tout assembly que je ne veux pas GAC doit vivre dans le répertoire d'exécution. Tout assembly qui n'est pas ou ne peut pas être dans le répertoire d'exécution I GAC (géré par des événements de construction automatiques).

Cela ne m'a posé aucun problème jusqu'à présent. Bien que je sois sûr qu'il y a une situation où cela ne fonctionnera pas, la réponse habituelle à tout problème est "oh, juste GAC!". 8 J

J'espère que cela pourra aider!

Tâche
la source
1

Bien que ce soit un vieux document, mais cela m'a aidé à résoudre le problème de l'ignorance de «HintPath» sur une autre machine. C'était parce que la DLL référencée devait également être dans le contrôle de code source:

https://msdn.microsoft.com/en-us/library/ee817675.aspx#tdlg_ch4_includeoutersystemassemblieswithprojects

Extrait:

Pour inclure puis référencer un assemblage de système externe
1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet qui doit référencer l'assembly ,, puis cliquez sur Ajouter un élément existant.
2. Naviguez jusqu'à l'assembly et puis cliquez sur OK. L'assemblage est ensuite copié dans le dossier du projet et automatiquement ajouté à VSS (en supposant que le projet est déjà sous contrôle de code source).
3. Utilisez le bouton Parcourir dans la boîte de dialogue Ajouter une référence pour définir une référence de fichier à l'assemblage dans le dossier du projet.
nkanani
la source