Kopiuj do katalogu wyjściowego kopiuje strukturę folderów, ale chce tylko kopiować pliki

87

Mam VS2008 Chcę skopiować określone pliki z katalogu do mojego /bin/folderu. Ustawiłem pliki (znajdujące się w/common/browserhawk/ ) na „Kopiuj do katalogu wyjściowego”. Jednak kopiuje również strukturę folderów: pliki są kopiowane do/bin/common/browserhawk/

Jak sprawić, by te pliki zostały skopiowane tylko /bin/? Nie chcę przechowywać ich w katalogu głównym witryny, aby można je było poprawnie skopiować.

Powiązane pytanie: Visual Studio dodaje pliki .dll i .pdb do projektu po kompilacji

Steve Wright
źródło

Odpowiedzi:

59

Możesz dodać zdarzenie po kompilacji, aby skopiować pliki.
Przejdź do właściwości projektu, zakładki Zdarzenia kompilacji i dodaj następujące polecenie do wiersza poleceń zdarzenia po kompilacji:

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

Pamiętaj, aby umieścić cudzysłowy, jeśli ścieżka projektu zawiera spacje.

Bill A.
źródło
Dziękuję za tę radę, ponieważ właśnie zadziałała dla mnie również w VS2012.
Dib
2
W moim przypadku nieco zmodyfikowałem to:xcopy /s /d /y "$(ProjectDir)\stuff" "$(TargetDir)\stuff"
Danny Staple
44

Ponieważ nie mogę komentować wcześniejszych odpowiedzi, rozwiązanie umieszczę tutaj:

Dodając do tego, co dostarczył @PaulAlexander, dodaj do swojego pliku .csproj / .vbproj:

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

Umożliwia to wybranie „RootContent” jako akcji kompilacji w oknie Właściwości, a dostęp do wszystkich można uzyskać za pośrednictwem interfejsu GUI. Bardziej szczegółowe wyjaśnienie: opcja „AvailableItemName” zasadniczo tworzy nową nazwaną listę, do której można przypisać elementy w projekcie we właściwości „Build Action” w oknie Properties. Możesz następnie użyć tej nowo utworzonej listy w dowolnym celu (np. Przez „@ (RootContent)”).

fala uderzeniowa
źródło
Dobra odpowiedź, po prostu wykorzystałem to do sukcesu!
Chris Marisic,
Zauważ również, że VS 2010 (nie jestem pewien co do starszych wersji) będzie narzekać, AvailableItemNameże jest nieprawidłowym elementem, jeśli edytujesz plik projektu w VS; po prostu zignoruj ​​ostrzeżenie, i tak działa.
Aaronaught
2
Niestety powoduje to skopiowanie pliku tylko do katalogu wyjściowego projektu, do którego należy plik - a nie do katalogu wyjściowego projektu startowego. Jest to ważne, gdy używasz tego w projekcie biblioteki.
Sebastian Krysmański
2
Działa to świetnie przy tworzeniu w trybie wydania i debugowania w vs2008, ale nie wydaje się działać przy korzystaniu z publikowania jednym kliknięciem. Jakieś sugestie?
Soenhay
2
Nie działał dla mnie w vs2015. Naprawiono przez nieco przepisanie celu: <Target Name="RootOutputCopyTarget" AfterTargets="Build">... </Target>
lorond
44

Jeśli edytujesz plik .csproj / .vbproj w edytorze tekstu, możesz kontrolować, gdzie plik zostanie umieszczony w katalogu wyjściowym, a także jaką nazwę będzie miał plik w katalogu wyjściowym. Na przykład:

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

Spowoduje to umieszczenie pliku content\someContent.txtw bin\someContentInOutputDirectory.txt. Możesz także wybrać podkatalog w, binjeśli chcesz; po prostu dodaj go do elementu Link.

Daniel Yankowsky
źródło
3
Wow, czy miałem szczęście, że potrzebowałem tego teraz, a nie dwa dni temu. Dzięki; to jest świetne!
Asherah
2
O mój Boże, dziękuję. Właśnie spędziłem 6 godzin próbując naprawić jakieś śmieci z narożnika, w których VS nie kopiował plików .dll w inteligentny sposób. To jest prawdziwa odpowiedź na życie, wszechświat i wszystko.
Brandon
5
To zdecydowanie najlepsze rozwiązanie
PhilHdt
1
Po wykonaniu tej czynności i ponownym załadowaniu projektu w programie Visual Studio zauważyłem, że pliki zależności zniknęły z eksploratora rozwiązań, jakby nie były zawarte w projekcie. Jednak nadal buduje się zgodnie z oczekiwaniami i kopiuje do wyniku zgodnie z potrzebami. Aby obejść ten problem, obecnie dodaję każdy plik dwukrotnie; raz bez żadnej akcji i raz z ustawionym „kopiuj na wyjście”.
Éliette
1
Nie jest to zamierzone użycie tego tagu. W VS2013 generuje ostrzeżenie podczas ładowania projektu, a plik nie jest widoczny jako dodany do projektu, ponieważ jest to katalog projektu.
jpmc26
15

Uważam, że polecenie XCOPY lepiej obsługuje katalogi i pliki. W związku z tym,

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

Co pozwala na tworzenie folderów poza katalogiem docelowym.

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

Struktura folderów / plików projektu:

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

Staje się:

    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
AMissico
źródło
/Dmoże być również przydatne, aby uniknąć nadpisywania ewentualnych zmian.
KurzedMetal
10

Dodaj następujące elementy do pliku .csproj / .vbproj

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

Następnie zmień akcję kompilacji dowolnych plików, które chcesz umieścić w folderze głównym, na RootContent.

Paul Alexander
źródło
Nie za pomocą okien dialogowych ... ale możesz edytować swój projekt w VS. Kliknij projekt prawym przyciskiem myszy i wybierz opcję Zwolnij projekt. Następnie kliknij prawym przyciskiem myszy i wybierz Edytuj. Następnie możesz edytować plik MSBuild, który jest Twoim projektem.
Paul Alexander,
2
Dzięki, wygląda na przydatne. Niestety, nawet po dodaniu fragmentu kodu do pliku .vbproj, RootContentnie pojawia się on na liście rozwijanej „Akcja kompilacji”, a wpisanie go ręcznie powoduje wyświetlenie błędu „Wartość właściwości jest nieprawidłowa” w programie Visual Studio. Co mnie ominęło?
Heinzi
Nie działa z projektem aplikacji konsoli programu Visual Studio 2010 C #.
AMissico
Nie działa z projektem aplikacji konsoli VB.NET programu Visual Studio 2010.
AMissico
Nie działa z projektem aplikacji konsoli programu Visual Studio 2008 C #.
AMissico
5

Użyłem tego w VS2010, VS2015, VS2017 i VS2019. Preferuję to rozwiązanie, ponieważ:

  1. Plik XML można ponownie wykorzystać w dowolnym projekcie
  2. „RootContent” jest wybierana jako akcja kompilacji w interfejsie użytkownika programu Visual Studio, tak jak każda inna „zawartość”
  3. „CopyToOutputDirectory” jest przestrzegany, tak jak można się tego spodziewać
  4. RootContent jest dodawany do danych wyjściowych projektu: jest przenoszony przez odniesienia do projektu, jest zgodny z zasadami „Clean” itp.
  5. RootContent można określić za pomocą symbolu wieloznacznego, zachowując rekursywną strukturę folderów:
<RootContent Include="common\browserhawk\**">
  <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</RootContent>

Na początku pliku projektu:

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

Zapożyczone z tej odpowiedzi

Po imporcie 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>

Zapożyczone z tej odpowiedzi

MattGerg
źródło
To dobrze - zamieniłbym się, RootContentco oznacza „zakodowane na stałe”, aby CustomContentwskazać, że jest to specjalistyczna zawartość, którą dodajemy do tego projektu i musimy skopiować w ten szczególny sposób. Poza tym musiałem TargetPath=%(RecursiveDir)%(Filename)%(Extension)odtworzyć strukturę folderów z określonych CustomContentplików do ścieżki wyjściowej.
Jonno
@Jonno Celem jest skopiowanie plików bezpośrednio do głównego katalogu wyjściowego, niezależnie od katalogu RecursiveDirectory. Wbudowana akcja budowania „Treści” już zapewnia nam mechanizm do kopiowania przy jednoczesnym zachowaniu RecursiveDirectory.
MattGerg
Od jakiegoś czasu nie miałem okazji tego testować, ale czy ustawienie akcji kompilacji „Treść” nie spowoduje, że pliki /common/browserhawk/zostaną skopiowane, /bin/common/browserhawk/jak powiedział OP? IIRC, moim zamiarem było, aby /common/browserhawk/a.txtskończyć w, /bin/a.txtale zezwolić na rekursję stamtąd, więc /common/browserhawk/secret/stuff.pngkończy się w /bin/secret/stuff.png.
Jonno
@Jonno Ok, tak, to ma teraz sens. Zaktualizowałem odpowiedź, aby uwzględnić rozszerzenie %(RecursiveDirectory). To jest naprawdę fajne, ponieważ oprócz wybierania pojedynczych plików w IDE możesz również określić wiele plików za pomocą symboli wieloznacznych. W przypadku użycia **symbolu wieloznacznego cała struktura folderów zostanie zachowana.
MattGerg
1
Wielkie dzięki za tak świetną odpowiedź! Myślę, że ta odpowiedź jest poprawna z następujących powodów: 1. Brak zewnętrznych poleceń cmd 2. cross platform
George Anisimov
2

Skończyło się na dodaniu kroku do pliku kompilacji nant do skopiowania po pomyślnym zakończeniu

<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>
Steve Wright
źródło
2
+1, ponieważ dla kogoś używającego nant jest to nadal pomocna odpowiedź
Chris Haines
1

Możesz zbudować plik wsadowy, aby skopiować pliki i wykonać go jako zdarzenie po kompilacji.

jvanderh
źródło
Skończyło się na tym, że zrobiłem to dla jednego z moich projektów (chociaż użyłem skryptu Pythona zamiast nietoperza).
Fire Lancer