Visual Studio: jak „skopiować do katalogu wyjściowego” bez kopiowania struktury folderów?

111

Mam kilka plików dll w folderze \ lib w folderze projektu. Na stronie właściwości dll wybrałem opcję „Build Action” jako „Content” i „Copy to Output Directory” jako „Copy always”.

Po zbudowaniu biblioteki dll są kopiowane, ale znajdują się one w \ bin \ Release \ lib, a nie w \ bin \ Release.

Czy istnieje sposób na skopiowanie plików dll do \ bin \ Release (a nie do \ bin \ Release \ lib) bez pisania skryptu po kompilacji lub uciekania się do nant itp.?

O jej
źródło

Odpowiedzi:

256

zamiast <Content>używać <ContentWithTargetPath>i określ ścieżkę docelową, na przykład:

<ItemGroup>
  <ContentWithTargetPath Include="lib\some_file.dat">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <TargetPath>some_file.dat</TargetPath>
  </ContentWithTargetPath>
</ItemGroup>

Należy zauważyć, że ten wpis może nie być widoczny w programie Visual Studio (2012, 2015, 2017), ale po ręcznym dodaniu do csproj pojawi się w programie Visual Studio. Jednak ścieżki docelowej nie będzie można edytować za pośrednictwem interfejsu użytkownika.

Daniel Zeitlin
źródło
2
Nie widzę ContentWithTargetPath jako opcji akcji kompilacji w VS 2015. Czy istnieje sposób, aby ją dodać?
Kim
1
Po ręcznym dodaniu wpisu w pliku .csproj pojawia się on jako opcja w środowisku IDE. Jednak nadal nie mogę edytować ścieżki docelowej z IDE.
Kim
9
Moim jedynym zmartwieniem jest to, że nie będzie to obsługiwane w przyszłych wersjach MSBuild / .NET / Visual Studio / Cokolwiek, ponieważ interfejs użytkownika VS2015 nie pokazuje tej opcji ani właściwości TargetPath.
MarioDS
1
To działa dla mnie. Żadna z pozostałych odpowiedzi nie działa dla mnie. To powinna być odpowiedź.
GunWanderer,
1
Zwróć uwagę, że ContentWithTargetPathkompilacja przyrostowa z przerwami (testowana na VS 2017 15.9.9)
Mads Ravn
26

Zachowaj je $(ProjectDir)\Lib, ale dodaj te pliki „ jako łącze ” do katalogu głównego pliku .csproj. Teraz zostaną skopiowane do bin \ Debug (lub dowolnego innego folderu wyjściowego) bez znajdowania się w lib.

EDYCJA: Ta odpowiedź została napisana dawno temu, gdy ContentWithTargetPath nie był dostępny w wersjach VS / MSBuild, których używałem. Pozostawiając tę ​​odpowiedź tutaj dla osób, które być może będą musiały używać starszej wersji VS. Przestańcie tego komentować, wszyscy wiemy, że są teraz lepsze sposoby.

Ani
źródło
4
Dzięki ananthonline. Próbowałem twoich kroków, ale to nie pomogło. Może robię coś złego. Oto co robię. Popraw, jeśli uważasz, że coś jest nie tak: 1. Wyklucz te biblioteki DLL z projektu, ale pozwól im znajdować się w bibliotece 2. Kliknij projekt prawym przyciskiem myszy i „Dodaj istniejące elementy”. Wybierz biblioteki DLL z biblioteki i dodaj je „jako łącze” 3. Kliknij prawym przyciskiem myszy biblioteki DLL i ponownie wybierz opcję „Zawsze kopiuj” w polu „Kopiuj do katalogu wyjściowego”. 4. Oczyść i odbuduj. Wynik: ponownie mam te biblioteki DLL w \ bin \ release \ lib
OhDear
1
Opublikuj zrzut ekranu swojego folderu rozwiązania po jego skonfigurowaniu
Ani
3
Jeśli spróbuję dodać link do pliku już w drzewie projektu, odmawia i zamiast tego po prostu włącza plik do projektu ponownie ...
Nyerguds
1
Podobnie jak @Nyerguds, doświadczam, że nie można dodać łącza do pliku, który jest już w drzewie projektu, więc ta odpowiedź nie rozwiązuje pytania.
Tore Østergaard
1
Czy nie zalewa katalogu głównego katalogu projektu w Eksploratorze rozwiązań? W przypadku wielu takich plików może to być problem. Zwykle katalog główny katalogu projektu zawiera już za dużo różnych plików.
Alex34758
10

Jeśli Twoim głównym zamiarem jest dołączenie bibliotek DLL bez zaśmiecania katalogu głównego projektu, innym rozwiązaniem jest przeniesienie bibliotek DLL do oddzielnego projektu udostępnionego i dodanie tego jako odniesienia w oryginalnym projekcie.

(Zauważ, że ten post nie odpowiada bezpośrednio na to pytanie, ponieważ nie zachowuje struktury folderów i projektu, ale uznałem to podejście za przydatne, ponieważ mogłem zrestrukturyzować mój projekt w moim przypadku i ponieważ chciałem uniknąć niektórych wady innych podejść tutaj.)

Kroki

  • Kliknij prawym przyciskiem myszy plik Solution -> Add -> New Project -> Shared Project
  • Dodaj biblioteki DLL do tego projektu (w katalogu głównym tego projektu, a nie w podfolderze „lib”)
  • (Sprawdź, czy właściwości pliku DLL są ustawione poprawnie, np. Build Action: ContentI Copy to Output Directory: Copy Always)
  • Kliknij prawym przyciskiem myszy oryginalny projekt References -> Add Reference -> Shared Projects
  • Wybierz współdzielony projekt, który utworzyłeś wcześniej

Konfiguracja wygląda następująco:

zrzut ekranu eksploratora rozwiązań

synek
źródło
2
Zdecydowanie proste i eleganckie rozwiązanie pozwalające zachować porządek w projekcie.
Ravi Ganesh
Nie mogłem zmusić go do pracy z plikami UAP i * .bin.
Matteo
7

Dodaj pliki dll jako odniesienie do projektu i do zestawu odniesień „Kopiuj lokalnie” na wartość true.

erik_nw
źródło
1
Dzięki Erik. Działa to doskonale, z wyjątkiem jednej biblioteki dll, której nie mogę dodać jako odniesienia. Błąd, który otrzymuję podczas dodawania jako odniesienie: Nie można dodać odniesienia do „libeay32.dll”. Upewnij się, że plik jest dostępny i że jest to prawidłowy zestaw lub składnik COM.
OhDear,
7
@MAnthony: Tylko zestawy .NET lub zestawy międzyoperacyjne COM można dodawać jako odwołania do projektu; natywne biblioteki DLL nie mogą być. Musisz znaleźć inny sposób na skopiowanie biblioteki DLL do \ bin \ Release.
Michael Liu,
Dzięki Erikowi, Michaelowi i ananthonline. Przepraszamy, nie mogę zatwierdzić twoich odpowiedzi i komentarzy, ponieważ nie mam wymaganych punktów reputacji.
OhDear,
1
W przypadku niezarządzanej biblioteki DLL musisz użyć metody, którą zasugerowałem poniżej.
Ani,
4

Jeśli chcesz skopiować pliki z katalogu Libs do folderu głównego VS2017:

<ItemGroup Condition="'$(Platform)' == 'x64'">
    <None Include="Libs\x64\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

Do dowolnego innego folderu, w tym folderu Libs (RecursiveDir)

<ItemGroup Condition="'$(Platform)' == 'x86'">
    <None Include="Libs\x86\**" Link="mycustomfolder\%(RecursiveDir)%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
dev-siberia
źródło
3

Wygląda na to, że w VisualStudio 2015, jeśli dll, które dodajesz za pomocą linku, znajdują się w podfolderze tego samego projektu - automatycznie zostaną umieszczone w folderze, a dane wyjściowe również zostaną umieszczone w folderze, tak jak widziałeś.

Jeśli dll znajdują się w innym projekcie lub katalogu na dysku, a nie w podfolderze projektu , możesz „Dodaj za pomocą linku”, a zostaną one umieszczone w katalogu głównym.

DefenestrationDay
źródło
To samo w VS2012. Odmawia uczynienia z nich linku i po prostu dodaje je jako treść. Ostatecznie, niestety, najłatwiejszym rozwiązaniem wydaje się zrzucenie ich do katalogu głównego projektu.
Nyerguds
0

Alternatywną metodą jest pozostawienie elementów jako typu None. W eksploratorze rozwiązań kliknij te, które chcesz wdrożyć, i ustaw Contentwłaściwość True.

Uwaga: zrobiłem to w VS2019 i rzeczy mogą się zmieniać z wersji na wersję.

Aby to zadziałało, kliknij prawym przyciskiem myszy swój projekt i wybierz „Zwolnij projekt”. Następnie kliknij prawym przyciskiem myszy rozładowany projekt i wybierz „Edytuj nazwę projektu.vcxproj”.

W edytorze przejdź do samego końca pliku i wstaw ten cel tuż przed końcowym </Project>znacznikiem:

  <Target Name="CopyContent" AfterTargets="Build">
    <Copy SourceFiles="@(None)" Condition="'%(None.DeploymentContent)' == 'true'" DestinationFolder="$(OutputPath)" ContinueOnError="true" />
  </Target>

Teraz kliknij prawym przyciskiem myszy rozładowany projekt i wybierz „Wczytaj ponownie projekt”. Wybierz, aby zapisać i zamknąć, jeśli zostanie wyświetlony monit.

Ustawiłem też OutputDirectoryna:

$(SolutionDir)bin\$(Configuration)\$(Platform)\

a IntermediateDirectorydo:

$(SolutionDir)obj\$(Configuration)\$(ProjectName)\$(Platform)\

na stronie Ogólne właściwości projektu. Spowoduje to umieszczenie danych wyjściowych w folderze „bin”, a pośrednie w folderze „obj” w katalogu głównym rozwiązania.

Uwaga: $(SolutionDir)nie jest zdefiniowana podczas uruchamiania programu MSBuild z wiersza polecenia. Istnieje sztuczka, której możesz użyć, aby zdefiniować to w folderze, w którym znajduje się plik .sln, za pomocą GetDirectoryNameOfFileAbove. (pozostawione jako ćwiczenie dla czytelnika). Wygląda też na to, że w 2019 roku i tak obsługują to poprawnie w wierszu poleceń. Tak :)$(SolutionDir) zawiera ukośnika spływu, stąd nikt po nim. Wyniki każdego z nich muszą mieć na końcu odwrotny ukośnik.

Jeśli posiadasz wersję Pro lub wyższą, nie rób tego za każdym razem, gdy musisz utworzyć projekt. To byłoby kiepskie. Zamiast tego, gdy już ustawisz projekt dokładnie tak, jak lubisz, wybierz Project -> Export Template. Nadajesz mu nazwę, a następnym razem, gdy chcesz utworzyć taki projekt, jak ten, po prostu wybierz tę nazwę w oknie dialogowym Nowy projekt. (Myślę, że w starszej wersji tak było Files -> Export Teamplate....)

ChuckEng
źródło
-1

Miałem ten sam problem z Visual Studio 2010 / C # Project.

W przypadku zestawów (tj. Posiadających interfejs .NET) użyj folderu „References” w projekcie w Eksploratorze rozwiązań. Kliknij go prawym przyciskiem myszy, wybierz „Dodaj istniejący element” i zlokalizuj swój zespół .dll.

Typowe pliki .dll można umieścić w podfolderze (jak wspomniano powyżej) i we właściwościach wybrać:

  • Build Action = "HelpFiles"
  • Copy To OutputDirectory = "Jeśli nowszy"

To zadziałało dla mnie dokładnie tak, jak było to pożądane - podczas kompilacji pliki .DLL są kopiowane do katalogu wyjściowego bez podfolderu "\ lib".

Petr Hendl
źródło