HintPath vs ReferencePath in Visual Studio

120

Was genau ist der Unterschied zwischen der HintPathin einer .csproj-Datei und der ReferencePathin einer .csproj.userDatei? Wir versuchen, uns auf eine Konvention festzulegen, bei der sich Abhängigkeits-DLLs in einem SVN-Repo "Releases" befinden und alle Projekte auf ein bestimmtes Release verweisen. Da verschiedene Entwickler unterschiedliche Ordnerstrukturen haben, funktionieren relative Referenzen nicht. Daher haben wir ein Schema entwickelt, mit dem eine Umgebungsvariable verwendet wird, die auf den Release-Ordner des jeweiligen Entwicklers verweist, um eine absolute Referenz zu erstellen. Nachdem eine Referenz hinzugefügt wurde, bearbeiten wir die Projektdatei manuell, um die Referenz mithilfe der Umgebungsvariablen in einen absoluten Pfad zu ändern.

Ich habe festgestellt, dass dies sowohl mit dem HintPathals auch mit dem möglich ist ReferencePath, aber der einzige Unterschied, den ich zwischen ihnen feststellen konnte, besteht darin, dass er HintPathbeim Erstellen und ReferencePathbeim Laden des Projekts in die IDE behoben wird. Ich bin mir jedoch nicht sicher, welche Konsequenzen dies hat. Ich habe bemerkt, dass VS das manchmal umschreibt .csproj.userund ich das umschreiben muss ReferencePath, aber ich bin nicht sicher, was das auslöst.

Ich habe gehört, dass es am besten ist, die .csproj.userDatei nicht einzuchecken, da sie benutzerspezifisch ist, daher möchte ich darauf abzielen, aber ich habe auch gehört, dass das HintPathLaden der angegebenen DLL nicht "garantiert" ist, wenn Die gleiche DLL befindet sich zB im Ausgabeverzeichnis des Projekts. Irgendwelche Gedanken dazu?

Toaster
quelle

Antworten:

133

Laut diesem MSDN-Blog: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Beim Erstellen gibt es eine Suchreihenfolge für Baugruppen. Die Suchreihenfolge lautet wie folgt:

  • Dateien aus dem aktuellen Projekt - angegeben durch $ {CandidateAssemblyFiles}.
  • $ (ReferencePath) -Eigenschaft, die aus der Benutzer- / Zieldatei stammt.
  • % (HintPath) -Metadaten, die durch das Referenzelement angegeben werden.
  • Ziel-Framework-Verzeichnis.
  • In der Registrierung gefundene Verzeichnisse, die die AssemblyFoldersEx-Registrierung verwenden.
  • Registrierte Assembly-Ordner, angegeben durch $ {AssemblyFolders}.
  • $ (OutputPath) oder $ (OutDir)
  • GAC

Wenn also die gewünschte Assembly von HintPath gefunden wird , aber mit ReferencePath eine alternative Assembly gefunden werden kann , wird die ReferencePath -Assembly der HintPath - Assembly vorgezogen .

ajs410
quelle
2
Außer, dass sie dies in VS2019 geändert haben - wir verwenden dieses Setup seit Jahren. nicht länger. Repository-Dateien haben jetzt eine höhere Priorität als Lösungs-Build-DLL-Dateien - siehe Abbildung :(
Christian
@Christian: Was sind Repository-Dateien? Haben Sie weitere Informationen dazu?
Testen
@testing Ich spreche von den externen Referenzpfaden, die Sie in Ihrem Projekt-Setup von VS festlegen können. Leider kann diese verrückte wichtige Einstellung für die Projektumgebung (wir haben drei verschiedene Umgebungen) nicht in den Projekteinstellungen gespeichert werden. Sie müssen es also explizit als Parameter zum Befehlszeilen-Kompilierungsskript hinzufügen.
Christian
31

Suchen Sie in der Datei Microsoft.Common.targets

Die Antwort auf die Frage befindet sich in der Datei Microsoft.Common.targetsfür Ihre Ziel-Framework-Version.

Für .Net Framework Version 4.0 (und 4.5!) Ist das AssemblySearchPaths-Element folgendermaßen definiert:

    <!--
    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>

Für .Net Framework 3.5 ist die Definition dieselbe, aber der Kommentar ist falsch. Die 2.0-Definition unterscheidet sich geringfügig und verwendet $ (OutputPath) anstelle von $ (OutDir).

Auf meinem Computer befinden sich die folgenden Versionen der Datei 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

Dies ist mit Visual Studio 2008, 2010 und 2013 unter Windows 7 installiert.

Die Tatsache, dass das Ausgabeverzeichnis durchsucht wird, kann etwas frustrierend sein (wie das Originalposter zeigt), da möglicherweise ein falscher Hinweispfad ausgeblendet wird. Die Lösung wird auf Ihrem lokalen Computer in Ordnung erstellt, bricht jedoch ab, wenn Sie in einer sauberen Ordnerstruktur (z. B. auf dem Buildcomputer) aufbauen.

Nils Lande
quelle
Ich habe ein ähnliches Problem. In diesem Fall, wo soll ich die DLL-Dateien platzieren? Framework oder Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev
5

Meine eigene Erfahrung hat gezeigt, dass es am besten ist, sich an eine von zwei Arten von Baugruppenreferenzen zu halten:

  • Eine 'lokale' Assembly im aktuellen Build-Verzeichnis
  • Eine Versammlung im GAC

Ich habe festgestellt (ähnlich wie Sie beschrieben haben), dass andere Methoden entweder zu leicht zu brechen sind oder lästige Wartungsanforderungen haben.

Jede Assembly, die ich nicht zu GAC machen möchte, muss im Ausführungsverzeichnis leben. Jede Assembly, die sich nicht im Ausführungsverzeichnis I GAC befindet oder nicht befinden kann (verwaltet durch automatische Build-Ereignisse).

Das hat mir bisher keine Probleme bereitet. Ich bin mir zwar sicher, dass es eine Situation gibt, in der es nicht funktioniert, aber die übliche Antwort auf jedes Problem war "Oh, nur GAC it!". 8 D.

Hoffentlich hilft das!

Aufgabe
quelle
1

Dies ist zwar ein altes Dokument, aber es hat mir geholfen, das Problem zu lösen, dass 'HintPath' auf einem anderen Computer ignoriert wird. Dies lag daran, dass sich die referenzierte DLL auch in der Quellcodeverwaltung befinden musste:

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

Auszug:

Einschließen und Verweisen auf eine Baugruppe des äußeren Systems
1. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf das Projekt, das auf die Assembly verweisen muss, und klicken Sie dann auf Vorhandenes Element hinzufügen.
2. Navigieren Sie zur Baugruppe und klicken Sie auf OK. Die Assembly wird dann in den Projektordner kopiert und automatisch zu VSS hinzugefügt (vorausgesetzt, das Projekt befindet sich bereits in der Quellcodeverwaltung).
3. Verwenden Sie die Schaltfläche Durchsuchen im Dialogfeld Referenz hinzufügen, um einen Dateiverweis auf Assembly im Projektordner festzulegen.
nkanani
quelle