Связанные файлы Visual Studio не существуют

17

В Visual Studio вы можете сделать Add - & gt; Existing Item , а затем Add as Link от кнопки снижения Add .

Это здорово. Это позволит вам добавить файл из другого проекта, и редактирование файла также редактирует его в исходном проекте.

Я хотел бы использовать эту функцию, чтобы иметь файл конфигурации (с именем Shared.config) во всех проектах в одном решении. И этот файл всегда будет таким же.

решение
|
| - проект 1
| - Shared.config [физический]
| - проект 2
| - Shared.config [связанный]

После публикации файл действительно попадает во все опубликованные проекты, поэтому проблем нет.

Но перед публикацией (во время разработки на сборке) связанный файл на самом деле не существует. Попытка увидеть файл в проводнике Windows доказывает, что файл отсутствует в каталоге проекта. Visual Studio только заставляет его выглядеть так, как будто он существует в проводнике решений. (Хотя на сборке связанные элементы, вероятно, скопированы в каталог bin , но я не хочу использовать / получать доступ к файлам из каталога bin .)

Теперь это дает проблемы с курса. Попытка распечатать System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath("Shared.config")) завершится с ошибкой до того, как проект будет опубликован, из-за того, что Shared.config еще не существует в корневом каталоге проекта.

Что я хотел бы сделать, и где мне нужна ваша помощь:

  • Я бы хотел, чтобы ON BUILD скопировал все связанные файлы из их исходного местоположения в целевое местоположение.

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

Обычно VS не позволит вам создать связанный элемент в каталоге, если этот каталог уже содержит файл с тем же именем.

Но, я тестировал, сначала создав связанный элемент; затем с помощью проводника Windows скопируйте исходный файл в целевой каталог и посмотрите, как работает Visual Studio. Исследователь решений просто скрывает физический файл и показывает связанный элемент вместо него. (Даже если вы нажмете Show all files в проводнике решений.)

решение
|
| - проект 1
| - Shared.config [физический]
| - проект 2
| - Shared.config [связанный]
| - Shared.config [физический, скопированный здесь во время сборки, невидимый в Solution explorer]

Это именно то, что я хочу! При попытке отредактировать файл Visual Studio откроет «связанный элемент». И при сборке физический файл будет скопирован в целевой каталог, чтобы он существовал для кода, который пытается получить к нему доступ.

Теперь, как мне это сделать? Должно ли это быть сделано с событиями Build? Если да, то как я могу сказать «копировать оригиналы всех связанных файлов в их целевой каталог?

    
задан nl-x 19.03.2013 в 17:59
источник

4 ответа

15

Вероятно, вы должны использовать функции MSBuild для реализации этого.

Отредактируйте файл csproj (в Visual Studio щелкните правой кнопкой мыши проект и выгрузите его, затем щелкните правой кнопкой мыши и отредактируйте)

Прокрутите вниз, и вы должны найти эту строку.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Сразу после этой строки добавьте эти строки.

  <ItemGroup>
    <LinkedItem Include="@(None)" Condition="'%Link' != ''" />
  </ItemGroup>
  <Target Name="CopyLinkedFiles" BeforeTargets="Build" Inputs="@(LinkedItem)" Outputs="@(LinkedItem->'%(Filename)%(Extension)')">
    <Copy SourceFiles="@(LinkedItem)" DestinationFolder="$(MSBuildProjectDirectory)" />
  </Target>

Теперь каждый раз, когда вы создаете, прямо перед действием сборки MSBuild копирует все связанные файлы.

Объяснение

ItemGroup содержит мой «массив» с именем «LinkedItem». Я генерирую этот массив, добавляя только элементы «Нет», которые содержат свойство ссылки.

Target - это концепция MSBuild. Вы можете думать об этом как о конкретном этапе построения. Я назвал этот этап «CopyLinkedFiles», но вы можете назвать его чем угодно.

BeforeTargets - это директива, которая сообщает MSBuild запускать действие до указанной фазы. Здесь я решил запустить «CopyLinkedFiles» перед фазой «Build».

Inputs - параметр оптимизации. Он используется для ускорения строительства путем пропуска копии, если это не необходимо. Вы можете игнорировать этот параметр, если вам все равно. MSBuild сравнивает Inputs с ожидаемой временной отметкой Outputs , чтобы увидеть, нужно ли ее выполнять.

Copy - это задача MSBuild, которая принимает файл для копирования и вывода в указанную папку.

Сокращение резервирования

Вы можете вставить это в каждый файл .csproj, или вы можете поместить его в центральный .proj и вставить его в файлы csproj. К сожалению, независимо от того, что вы делаете, вам придется редактировать каждый .csproj как минимум 1 раз. : (

Создайте файл в общем вызове проекта WhateverNameYouLike.proj Поместите это содержимое в файл.

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <!-- paste the previously shown code here -->

  <!-- you can save yourself some hassle by linking the config file here, but if you really enjoy adding the file as a link to every project, you can skip this line -->
  <None Include="..\Common\Shared.config">
    <Link>Shared.config</Link>
  </None>
</Project>

Теперь раздражающая часть: В каждом .csproj вам нужно будет добавить строку типа   %код% вероятно, в конце перед тегом закрытия <Import Project="..\Common\WhateverNameYouLike.proj" /> .

    
ответ дан dss539 19.03.2013 в 18:25
источник
23

У меня были некоторые проблемы с ответ dss539 (протестирован vs2010). Во-первых, дубликаты появились в обозревателе решений для каждого сопоставленного файла. Во-вторых, '%link' не является аксессуаром свойства, это сама строка, и она всегда не равна пустой строке '' , поэтому каждый файл с действием None build был сопоставлен, дублирован и скопирован при сборке. В-третьих, связанные файлы копируются в корневой каталог проекта, но мне нужны файлы для копирования, где размещаются ссылки. Поэтому я внесла некоторые изменения:

<Target Name="CopyLinkedFiles" BeforeTargets="Build">
  <ItemGroup>
    <LinkedItem Include="@(Content)" Condition="%(Content.Link) != ''" />
  </ItemGroup>
  <Copy SourceFiles="@(LinkedItem)" DestinationFiles="%(LinkedItem.Link)"/> 
</Target>

LinkedItem больше не дублирует элементы в проводнике решений. Чтобы скопировать ссылку, вам необходимо установить действие Content build.

    
ответ дан lorond 02.07.2013 в 16:59
источник
1

Щелкните правой кнопкой мыши связанный файл конфигурации, выберите свойства, измените Copy to Output Directory с Never на Copy always .

    
ответ дан Michael Sallmen 19.03.2013 в 18:12
источник
0

Вы можете создавать события предварительной и последующей сборки в Visual Studio.

Выберите проект, щелкните правой кнопкой мыши, свойства, события сборки.

Для предварительной сборки -

copy /y "$(LocationOfShared.Config)Shared.config\" "$(TargetDir)"

Для пост-сборки

cd $(TargetDir)
del shared.config

Очевидно, вам нужно будет поиграть с фактическими местоположениями, которые будут возвращены, но вы получите эту идею.

Изменить - приведенные выше ответы проще и понятнее, но это должно работать как круглый способ сделать это.

    
ответ дан Alexander Matusiak 19.03.2013 в 18:13
источник