HintPath vs ReferencePath у Visual Studio


120

Що ж являє собою різницю між HintPathв файлі .csproj і ReferencePathв .csproj.userфайлі? Ми намагаємося взяти на себе конвенцію, де DLL-файли залежності знаходяться у репозиторії svn repo та всі проекти вказують на певний випуск. Оскільки різні розробники мають різні структури папок, відносні посилання не працюватимуть, тому ми створили схему використання змінної середовища, яка вказує на папку випусків конкретного розробника для створення абсолютної посилання. Тож після додавання посилання ми вручну редагуємо файл проекту, щоб змінити посилання на абсолютний шлях за допомогою змінної середовища.

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

Я чув, що найкраще не перевіряти .csproj.userфайл, оскільки він є специфічним для користувача, тому я хотів би прагнути до цього, але також чув, що HintPathDLL-специфіку не гарантовано завантажується, якщо та сама 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 Registration.
  • Зареєстровані папки збірки, вказані $ {AssemblyFolders}.
  • $ (OutputPath) або $ (OutDir)
  • GAC

Отже, якщо потрібна збірка знайдена HintPath , але альтернативна збірка може бути знайдена за допомогою ReferencePath , вона віддасть перевагу збірці ReferencePath 'd, а не HintPath ' d.


2
За винятком того, що вони змінили це в VS2019 - ми використовуємо цю установку вже багато років. більше не. Файли репозиторії зараз мають більш високий пріоритет, ніж файли DLL для побудови рішення - перейдіть до фігури :(
Крістіан

@Christian: Що таке файли репозиторію? Чи маєте ви більше інформації про це?
тестування

@ тестування Я говорю про зовнішні опорні шляхи, які ви можете встановити в проекті налаштування 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? Рамка чи Framework64? stackoverflow.com/questions/45945579/…
Chetan Sachdev

5

Мій власний досвід полягав у тому, що найкраще дотримуватися одного з двох видів посилань на збірку:

  • "Локальна" збірка в поточному каталозі збірки
  • Збори в GAC

Я знайшов (приблизно так, як ви описали) інші методи, які можна занадто легко зламати або мати набридливі вимоги до обслуговування.

Будь-яка збірка, яку я не хочу в GAC, повинна жити в каталозі виконання. Будь-яка збірка, яка не знаходиться або не може бути в каталозі виконання I GAC (керується подіями автоматичної збірки).

Це досі не дало мені жодних проблем. Хоча я впевнений, що існує ситуація, коли це не спрацює, звичайна відповідь на будь-яку проблему була "о, просто GAC це!". 8 Д

Сподіваюся, що це допомагає!


1

Хоча це старий документ, але він допоміг мені вирішити проблему ігнорування 'HintPath' на іншій машині. Це пояснювалося тим, що DLL, на який посилається, також повинен був знаходитись у контролі джерела:

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

Витяг:

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