HintPath против ReferencePath в Visual Studio


120

В чем именно разница между HintPathв файле .csproj и ReferencePathв .csproj.userфайле? Мы пытаемся придерживаться соглашения, в котором библиотеки зависимостей находятся в репозитории svn «выпусков», а все проекты указывают на конкретный выпуск. Поскольку у разных разработчиков разные структуры папок, относительные ссылки работать не будут, поэтому мы придумали схему использования переменной среды, указывающей на папку релизов конкретного разработчика, для создания абсолютной ссылки. Итак, после добавления ссылки мы вручную редактируем файл проекта, чтобы изменить ссылку на абсолютный путь с помощью переменной среды.

Я заметил, что это можно сделать как с помощью, так HintPathи с помощью ReferencePath, но единственное различие, которое я смог найти между ними, заключается в том, что HintPathоно разрешается во время сборки и ReferencePathкогда проект загружается в IDE. Я не совсем уверен, каковы последствия этого. Я заметил, что VS иногда переписывает, .csproj.userи мне приходится переписывать ReferencePath, но я не уверен, что это вызывает.

Я слышал, что лучше не проверять .csproj.userфайл, поскольку он специфичен для пользователя, поэтому я бы хотел добиться этого, но я также слышал, что HintPathуказанная DLL не "гарантированно" будет загружена, если та же DLL находится, например, в выходном каталоге проекта. Есть мысли по этому поводу?

Ответы:


133

Согласно этому блогу MSDN: https://blogs.msdn.microsoft.com/manishagarwal/2005/09/28/resolving-file-references-in-team-build-part-2/

При сборке есть порядок поиска сборок. Порядок поиска следующий:

  • Файлы из текущего проекта - обозначаются $ {CandidateAssemblyFiles}.
  • $ (ReferencePath) из файла .user / target.
  • % (HintPath) метаданные, указанные ссылочным элементом.
  • Каталог целевой платформы.
  • Каталоги, найденные в реестре, который использует регистрацию AssemblyFoldersEx.
  • Зарегистрированные папки сборки, обозначенные $ {AssemblyFolders}.
  • $ (OutputPath) или $ (OutDir)
  • GAC

Итак, если желаемая сборка найдена с помощью HintPath , но альтернативная сборка может быть найдена с помощью ReferencePath , она предпочтет сборку ReferencePath 'd сборке HintPath ' d.


2
За исключением того, что они изменили это в VS2019 - мы используем эту настройку уже много лет. уже нет. Файлы репозитория теперь имеют более высокий приоритет, чем файлы dll сборки решения - иди на цифру :(
Christian

@Christian: Что такое файлы репозитория? У вас есть дополнительная информация об этом?
тестирование

@testing Я говорю о путях внешних ссылок, которые вы можете установить в своем проекте в настройке VS. К сожалению, этот безумно важный параметр для среды проекта (у нас есть три разных среды) не может быть сохранен в настройках проекта; поэтому вам нужно явно добавить его как параметр в сценарий компиляции командной строки.
Кристиан

31

Посмотрите в файле Microsoft.Common.targets

Ответ на вопрос находится в файле Microsoft.Common.targetsдля вашей целевой версии фреймворка.

Для .Net Framework версии 4.0 (и 4.5!) Элемент AssemblySearchPaths определяется следующим образом:

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

Для .Net Framework 3.5 определение такое же, но комментарий неверный. Определение 2.0 немного отличается, в нем используется $ (OutputPath) вместо $ (OutDir).

На моем компьютере установлены следующие версии файла 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

Это с Visual Studio 2008, 2010 и 2013, установленным в Windows 7.

Тот факт, что выполняется поиск в выходном каталоге, может немного расстраивать (как указывает исходный плакат), потому что он может скрывать неверный HintPath. Решение работает нормально на вашем локальном компьютере, но ломается, когда вы создаете чистую структуру папок (например, на машине сборки).


У меня аналогичная проблема, в таком случае, где мне разместить файлы dll? Framework или Framework64? stackoverflow.com/questions/45945579/…
Четан Сачдев,

5

По моему собственному опыту, лучше придерживаться одного из двух типов ссылок на сборку:

  • "Локальная" сборка в текущем каталоге сборки
  • Сборка в GAC

Я обнаружил (как вы описали) другие методы, которые либо слишком легко сломать, либо требуют раздражающих требований к обслуживанию.

Любая сборка, которую я не хочу передавать в GAC, должна находиться в каталоге выполнения. Любая сборка, которая не находится или не может находиться в каталоге выполнения I GAC (управляется событиями автоматической сборки).

Пока это не дало мне никаких проблем. Хотя я уверен, что есть ситуация, когда это не сработает, обычным ответом на любую проблему было «о, просто GAC!». 8 Д

Надеюсь, это поможет!


1

Хотя это старый документ, но он помог мне решить проблему игнорирования HintPath на другом компьютере. Это произошло потому, что указанная DLL также должна быть в системе управления версиями:

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

Выдержка:

Чтобы включить сборку внешней системы и затем сослаться на нее
1. В обозревателе решений щелкните правой кнопкой мыши проект, который должен ссылаться на сборку, и выберите «Добавить существующий элемент».
2. Перейдите к сборке и нажмите OK. Затем сборка копируется в папку проекта и автоматически добавляется в VSS (при условии, что проект уже находится в системе управления версиями).
3. Используйте кнопку «Обзор» в диалоговом окне «Добавить ссылку», чтобы задать ссылку на файл для сборки в папке проекта.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.