Установить "Копировать локальный" в Ложь по умолчанию?

Могу ли я установить для параметра по умолчанию "Копировать локальный" в Visual Studio значение False? В большинстве случаев, когда я добавляю dll в качестве зависимости проекта, я хочу, чтобы свойство Copy Local было установлено в False. По умолчанию это правда. Есть ли способ изменить поведение Visual Studio по умолчанию? (2008)

6 ответов

Решение

Нет - Visual Studio использует внутренний набор правил, чтобы определить, на что следует установить функцию Копировать локально.

Из MSDN:

  1. Если ссылка - это другой проект, называемый ссылкой "проект-проект", то значение равно true.
  2. Если сборка найдена в глобальном кэше сборок, значение равно false.
  3. В особом случае значение для ссылки mscorlib.dll равно false.
  4. Если сборка находится в папке Framework SDK, то значение равно false.
  5. В противном случае значение истинно.

На самом деле, вы можете. Вам нужна пара вещей:

  1. Создайте .targets файл, который делает copylocal (<Private> тег, если быть точным) по умолчанию false.
  2. Импортировать цель в .csproj файлы. Вы можете добавить его в самой последней строке, перед закрытием </Project> тег, это будет выглядеть <Import Project="..\Build\yourtarget.targets" />,

Теперь у каждого проекта с этой целью по умолчанию отключен copylocal.

Недостатком является то, что вам нужно изменить каждый файл csproj, включая новые. Вы можете обойти новую проблему проекта, изменив шаблон проекта VS. Вместо Class.cs описанный в статье блога, необходимо изменить Class.vstemplate (в том же ZIP-файле).

При таком подходе есть еще одна проблема - сам путь. Если вы используете жестко запрограммированный относительный путь во вновь создаваемых файлах csproj, они могут быть неверными (если у вас нет плоской структуры проекта).

Вы можете:

  • Сделать VS генерировать правильный относительный путь. Не уверен, как это сделать, и если это вообще возможно.
  • Не обращайте на это внимания и вручную изменяйте путь для каждого нового csproj (в зависимости от количества новых проектов, которые у вас есть, хотя это и не идеально, что может быть допустимо).
  • Используйте переменную среды вместо относительного пути. В этом случае каждому разработчику потребуется один и тот же набор переменных.

Должно быть лучшее решение для этого, но еще не нашли его.

Начиная с msbuild v 15, вы можете скопировать один файл с именем Directory.Build.props в корневую папку, содержащую ваш источник:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemDefinitionGroup>
  <Reference>
    <Private>False</Private>
  </Reference>
  <ProjectReference>
     <Private>False</Private>
  </ProjectReference>
</ItemDefinitionGroup>
</Project>

Больше нечего делать! Это хорошо работает с Visual Studio 2017, а также с vNext Build. Возможно, вам придется закрыть Visual Studio, а затем снова открыть свое решение, чтобы применить эффект файла.

https://docs.microsoft.com/en-us/visualstudio/msbuild/customize-your-build

Мы не используем файлы.targets (как предложено в ответе ya23), поэтому мы просто редактируем .csproj файл проекта вручную в текстовом редакторе и добавьте <Private> элемент к ссылке, как это:

<Reference Include="[...]">
  <Private>False</Private>
  [...]
</Reference>

Значение <Private> элемент соответствует значению свойства "Копировать локально". Например, если <Private> имеет значение False, тогда "Копировать локально" также ложно.

Что касается решения, опубликованного @herzbube, если вы хотите отключить "Копировать локально" для всех (или большинства) ссылок в вашем файле .csproj, вам не нужно устанавливать <Private>False</Private> индивидуально на каждом Reference Вы можете просто поместить следующее прямо в .csproj:

<ItemDefinitionGroup>
  <Reference>
    <Private>False</Private>
  </Reference>
</ItemDefinitionGroup>

Это не влияет на проекты, на которые ссылаются <ProjectReference>, но вы можете сделать то же самое - либо вместо, либо также - для тех:

<ItemDefinitionGroup>
  <ProjectReference>
    <Private>False</Private>
  </ProjectReference>
</ItemDefinitionGroup>

Если вы хотите оба из них, вы можете объединить их в одну группу:

<ItemDefinitionGroup>
  <Reference>
    <Private>False</Private>
  </Reference>
  <ProjectReference>
    <Private>False</Private>
  </ProjectReference>
</ItemDefinitionGroup>

Убедитесь, что вы поместили эти переопределения до первого фактического <Reference ...> или же <ProjectReference ...> Вы хотите повлиять, потому что эти блоки будут применяться только к тем ссылкам, которые появляются под ними. Затем, если есть некоторые из них, которые вы на самом деле хотите скопировать локально, вы можете просто перезаписать их обратно индивидуально (т.е. внутри самого тега), на этот раз используя True,

Для более сложных случаев вы можете переключать переопределяющее значение назад и вперед между True и False несколько раз в одном и том же файле.csproj. Другим продвинутым методом было бы стратегически разместить некоторые из ваших ссылок под этими блоками, а другие выше, чтобы на них не влияли.

Все это должно сделать XML в вашем.csproj намного чище и проще для чтения. Но есть еще больше хороших новостей, так что читайте дальше...


Что касается выбора, какие проекты должны быть отмечены <Private>False</Private> это обычно зависит от конкретной ситуации, но есть кое-что фундаментальное, что каждый может и должен сделать для начала. Это настолько простой, простой и эффективный шаг, который обеспечивает такие огромные улучшения надежности MSBuild 1. и ускорение времени сборки - и с небольшим недостатком - что каждое крупное решение, которое использует вывод C# по умолчанию (то есть локальный для проекта), выводит Места должны почти всегда делать эту корректировку:

В любом решении Visual Studio, которое создает несколько библиотек классов C# с любым нетривиальным числом <ProjectReference> взаимозависимости, что приводит к созданию еще одного приложения (т.е. исполняемых файлов):

  1. В верхней части.csproj для каждой библиотеки классов вставьте <ProjectReference> блок показан выше.
    ПРИЧИНА: Нет необходимости в том, чтобы какой-либо .dll собирал какие-либо библиотеки, на которые он ссылается, в свой собственный подкаталог, поскольку из этого расположения никогда не запускался исполняемый файл. Такое безудержное копирование является бесполезной занятой работой и может излишне замедлять вашу сборку, возможно, весьма радикально.

  2. С другой стороны, не изменяйте.csproj ни для одного из приложений вашего решения.
    ПРИЧИНА: Исполняемые файлы должны иметь все необходимые частные библиотеки в своих соответствующих подкаталогах, но сборка для каждого отдельного приложения должна отвечать за индивидуальный сбор каждой зависимости непосредственно из соответствующего подкаталога в подкаталог приложения. каталог.

Это прекрасно работает, потому что.csproj для библиотеки классов может ссылаться на несколько других библиотек классов, но.csproj для исполняемого файла обычно никогда не ссылается на другой исполняемый файл. Таким образом, для каждой локальной библиотеки, единственная .dll в ее bin папка будет сама по себе, тогда как каждое локально построенное приложение будет содержать полный набор локально собранных библиотек, на которые оно ссылается.

Удобно, что ничего не меняется для ссылочных библиотек, которые не созданы вашим решением, так как они обычно используют <Reference> вместо <ProjectReference> и мы не изменили прежний тег вообще. Но обратите внимание на только что упомянутое предположение; если он нарушается некоторыми вашими проектами, возможно, вам придется внести некоторые коррективы.

[1.] Повышение надежности может быть связано с конфликтами файлов, которые могут возникать при сборе одной и той же библиотеки из нескольких непересекающихся путей в графе зависимостей, особенно в параллельных сборках.

Поднятие этого, потому что кажется, что теперь есть пакет nuget, позволяющий именно это...

https://nuget.org/packages/CopyLocalFalse

Еще не пробовал, просто надеюсь, что это поможет.

Другие вопросы по тегам