HintPath vs ReferencePath w programie Visual Studio

120

Jaka jest dokładnie różnica między HintPathw pliku .csproj a ReferencePathw .csproj.userpliku? Staramy się przestrzegać konwencji, w której biblioteki DLL zależności znajdują się w repozytorium svn „wydań”, a wszystkie projekty wskazują na określone wydanie. Ponieważ różni programiści mają różne struktury folderów, odniesienia względne nie będą działać, więc wymyśliliśmy schemat użycia zmiennej środowiskowej wskazującej na folder wydań konkretnego programisty, aby utworzyć odniesienie bezwzględne. Dlatego po dodaniu odwołania ręcznie edytujemy plik projektu, aby zmienić odwołanie na ścieżkę bezwzględną za pomocą zmiennej środowiskowej.

Zauważyłem, że można to zrobić za pomocą obu HintPathi ReferencePath, ale jedyną różnicą, jaką mogłem znaleźć między nimi, jest to, że HintPathjest to rozwiązywane w czasie kompilacji i ReferencePathkiedy projekt jest ładowany do IDE. Nie jestem jednak pewien, jakie są tego konsekwencje. Zauważyłem, że VS czasami przepisuje .csproj.useri muszę przepisać ReferencePath, ale nie jestem pewien, co to powoduje.

Słyszałem, że najlepiej nie wpisywać .csproj.userpliku, ponieważ jest on specyficzny dla użytkownika, więc chciałbym dążyć do tego, ale słyszałem też, że HintPathokreślona biblioteka DLL nie jest „gwarantowana” do załadowania, jeśli ta sama biblioteka DLL znajduje się np. w katalogu wyjściowym projektu. Jakieś przemyślenia na ten temat?

mini piekarnik
źródło

Odpowiedzi:

133

Według tego bloga MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

Podczas budowania istnieje kolejność wyszukiwania zespołów. Kolejność wyszukiwania jest następująca:

  • Pliki z bieżącego projektu - wskazane przez $ {CandidateAssemblyFiles}.
  • Właściwość $ (ReferencePath) pochodząca z pliku .user / cele.
  • % (HintPath) metadane wskazane przez element referencyjny.
  • Docelowy katalog frameworka.
  • Katalogi znalezione w rejestrze korzystającym z rejestracji AssemblyFoldersEx.
  • Zarejestrowane foldery zespołu, wskazane przez $ {AssemblyFolders}.
  • $ (OutputPath) lub $ (OutDir)
  • GAC

Tak więc, jeśli żądany zestaw zostanie znaleziony przez HintPath , ale alternatywny zestaw można znaleźć za pomocą ReferencePath , będzie preferować zestaw ReferencePath 'd od HintPath ' d.

ajs410
źródło
2
Tyle że zmienili to w VS2019 - używamy tej konfiguracji od lat. nigdy więcej. Pliki repozytorium mają teraz wyższy priorytet niż pliki dll kompilacji rozwiązania - zobacz rysunek :(
Christian
@Christian: Co to są pliki repozytorium? Czy masz więcej informacji na ten temat?
testowanie
@testing Mówię o zewnętrznych ścieżkach referencyjnych, które możesz ustawić w konfiguracji projektu VS. Niestety tego szalonego, ważnego ustawienia dla środowiska projektu (mamy trzy różne środowiska), nie można zapisać w ustawieniach projektu; więc musisz jawnie dodać go jako parametr do skryptu kompilacji wiersza poleceń.
Christian,
31

Poszukaj w pliku Microsoft.Common.targets

Odpowiedź na pytanie znajduje się w pliku Microsoft.Common.targetsdla docelowej wersji platformy.

W przypadku .Net Framework w wersji 4.0 (i 4.5!) Element AssemblySearchPaths jest zdefiniowany w następujący sposób:

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

W przypadku .Net Framework 3.5 definicja jest taka sama, ale komentarz jest nieprawidłowy. Definicja 2.0 jest nieco inna, używa $ (OutputPath) zamiast $ (OutDir).

Na moim komputerze mam następujące wersje pliku 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

Dotyczy to programu Visual Studio 2008, 2010 i 2013 zainstalowanego w systemie Windows 7.

Fakt, że katalog wyjściowy jest przeszukiwany, może być nieco frustrujący (jak wskazuje oryginalny plakat), ponieważ może ukrywać nieprawidłową HintPath. Rozwiązanie buduje się poprawnie na komputerze lokalnym, ale psuje się, gdy tworzysz w czystej strukturze folderów (np. Na komputerze kompilacji).

Nils Lande
źródło
Mam podobny problem, w tym przypadku gdzie mam umieścić pliki dll? Framework czy Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev
5

Z własnego doświadczenia wiem, że najlepiej jest trzymać się jednego z dwóch rodzajów odniesień do montażu:

  • Zestaw „lokalny” w bieżącym katalogu kompilacji
  • Zgromadzenie w GAC

Znalazłem (podobnie jak opisałeś) inne metody, które albo są zbyt łatwe do złamania, albo mają irytujące wymagania konserwacyjne.

Każdy zestaw, którego nie chcę GAC, musi żyć w katalogu wykonawczym. Dowolny zestaw, który nie znajduje się lub nie może znajdować się w katalogu wykonywania I GAC (zarządzany przez zdarzenia kompilacji automatycznej).

Jak dotąd nie sprawiało mi to żadnych problemów. Chociaż jestem pewien, że jest sytuacja, w której to nie zadziała, zwykle odpowiedzią na każdy problem było „och, po prostu GAC to!”. 8 D

Mam nadzieję, że to pomoże!

Zadanie
źródło
1

Chociaż jest to stary dokument, pomógł mi rozwiązać problem ignorowania ścieżki „HintPath” na innym komputerze. Było tak, ponieważ przywoływana biblioteka DLL również musiała znajdować się w kontroli źródła:

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

Fragment:

Aby uwzględnić, a następnie odwołać się do zespołu systemu zewnętrznego
1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt, który musi odwoływać się do zestawu, a następnie kliknij polecenie Dodaj istniejący element.
2. Przejdź do zestawu, a następnie kliknij przycisk OK. Zespół jest następnie kopiowany do folderu projektu i automatycznie dodawany do VSS (zakładając, że projekt jest już pod kontrolą źródła).
3. Użyj przycisku Przeglądaj w oknie dialogowym Dodaj odniesienie, aby ustawić odniesienie do pliku assemblera w folderze projektu.
nkanani
źródło