Копировать в каталог вывода копирует структуру папок, но только для копирования файлов

У меня есть VS2008. Я хочу скопировать определенные файлы из каталога в папку /bin/. Я установил файлы (расположенные в /common/browserhawk/) в "Копировать в выходной каталог". Однако он также копирует структуру папок: файлы копируются в /bin/common/browserhawk/

Как мне получить эти файлы для копирования только /bin/? Я не хочу хранить их в корневом каталоге веб-сайта, чтобы заставить их правильно копировать.

Связанный с нами вопрос: Visual Studio добавляет DLL и .pdb для проекта после компиляции

Ответ 1

Вы можете добавить сообщение Post Build, чтобы скопировать файлы.
Перейдите к свойствам проекта, вкладке "События" и добавьте следующее в командную строку события "После сборки":

copy "$(ProjectDir)\common\browserhawk\*.*" "$(TargetDir)"

Обязательно укажите кавычки, если в вашем пути к проекту есть пробелы.

Ответ 2

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

Добавьте к тому, что предоставил @PaulAlexander, добавьте следующее в ваш файл .csproj/.vbproj:

<ItemGroup>
    <AvailableItemName Include="RootContent">
      <Visible>false</Visible>
    </AvailableItemName>  
</ItemGroup>
<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

Это позволяет вам выбрать "RootContent" в качестве действия "Построение" в окне "Свойства", и к нему можно получить доступ через GUI. Более полное объяснение: опция "AvailableItemName" в основном создает новый именованный список, который вы можете назначить элементам проекта под свойством "Build Action" в окне "Свойства". Затем вы можете использовать этот вновь созданный список в любом целевом объекте (например, через "@(RootContent)" ).

Ответ 3

Если вы редактируете .csproj/.vbproj в текстовом редакторе, вы можете контролировать, где находится файл в выходном каталоге, а также то, что имя файла будет в выходном каталоге. Например:

<None Include="content\someContent.txt">
  <Link>someContentInOutputDirectory.txt</Link>
  <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>

Это положит файл content\someContent.txt в bin\someContentInOutputDirectory.txt. Вы также можете выбрать подкаталог в bin, если хотите; просто добавьте его в элемент "Ссылка".

Ответ 4

Я считаю, что команда XCOPY лучше обрабатывает каталоги и файлы. Следовательно,

    XCOPY "$(ProjectDir)common/browserhawk" "$(TargetDir)" /E /I /F /Y

Это позволяет создавать папки из целевого каталога.

    XCOPY "$(ProjectDir)Templates" "$(TargetDir)" /E /I /F /Y

Папка/файловая структура Project:

    A:\TEMP\CONSOLEAPPLICATION3\TEMPLATES
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt

становится:

    A:\TEMP\CONSOLEAPPLICATION3\BIN\DEBUG
    │   ConsoleApplication3.exe
    │   ConsoleApplication3.pdb
    │   ConsoleApplication3.vshost.exe
    │   ConsoleApplication3.vshost.exe.manifest
    ├───NewFolder1
    ├───NewFolder2
    │       TextFile1.txt
    │       TextFile2.txt
    │
    └───NewFolder3
            TextFile1.txt
            TextFile2.txt
            TextFile3.txt

Ответ 5

Добавьте в файл .csproj/.vbproj следующее:

<Target Name="AfterBuild">
    <Copy
        DestinationFolder="$(OutputPath)"
        SourceFiles="@(RootContent)"
        SkipUnchangedFiles="true"
        />  
</Target>

Затем измените действие сборки любых файлов, которые вы хотите в корневой папке, на RootContent.

Ответ 6

Я использовал это в VS2010 и VS2015. Я предпочитаю это решение, потому что:

  • XML может использоваться повторно в любом проекте
  • "RootContent" выбран как действие сборки в пользовательском интерфейсе Visual Studio, как и любой другой "контент"
  • "CopyToOutputDirectory" соблюдается, как и ожидалось.
  • RootContent добавляется к выходу проекта: переносится через Project-References, подчиняется "Clean" и т.д.
  • RootContent может быть задан с помощью подстановочного знака, сохраняя структуру рекурсивных папок:
    <RootContent Include="common\browserhawk\**">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </RootContent>
    

К началу файла проекта:

  <ItemGroup>
    <AvailableItemName Include="RootContent">
      <!-- Add "RootContent" as a choice in the "Build Action" dropdown. -->
      <Visible>False</Visible>
    </AvailableItemName>
  </ItemGroup>

Заимствован из этого ответа

После импорта Microsoft.targets Импорт:

  <PropertyGroup>
    <AssignTargetPathsDependsOn>
      $(AssignTargetPathsDependsOn);
      IncludeRootContentAsContent;
    </AssignTargetPathsDependsOn>
  </PropertyGroup>
  <Target Name="IncludeRootContentAsContent">
    <CreateItem Include="@(RootContent)" AdditionalMetadata="TargetPath=%(RecursiveDir)%(Filename)%(Extension)">
      <Output ItemName="ContentWithTargetPath" TaskParameter="Include" />
    </CreateItem>
  </Target>

Заимствован из этого ответа

Ответ 7

В итоге я добавил шаг к файлу сборки nant для копирования после успешного выполнения

<target name="action.copy.browserhawk.config" depends="compile.source">
    <copy todir="${App.Web.dir}/bin/" includeemptydirs="false">
        <fileset basedir="${browserhawk.config.dir}">
            <include name="bhawk_bb.dat" />
            <include name="bhawk_sp.dat" />
            <include name="browserhawk.properties" />
            <include name="maindefs.bdd" />
            <include name="maindefs.bdf" />
            <include name="BH_PRO.lic" />
        </fileset>
    </copy>
    <echo message="COPY BROWSERHAWK CONFIG: SUCCESS   ${datetime::now()}" />
</target>

Ответ 8

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