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

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.


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)”).


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.


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

/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.


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


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>

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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.