Visual Studio: come "copiare nella directory di output" senza copiare la struttura delle cartelle?


111

Ho alcuni file dll nella cartella \ lib della cartella del mio progetto. Nella pagina delle proprietà di dll, ho selezionato "Build Action" come "Content" e "Copy to Output Directory" come "Copy always".

Dopo la compilazione, sto effettivamente copiando la dll ma sono all'interno di \ bin \ Release \ lib e non in \ bin \ Release.

C'è un modo per copiare i file dll in \ bin \ Release (e non in \ bin \ Release \ lib) senza scrivere uno script post-build o ricorrere a nant ecc?

Risposte:


256

invece di <Content>utilizzare <ContentWithTargetPath>e specificare il percorso di destinazione, in questo modo:

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

Si noti che questa voce potrebbe non essere visibile da Visual Studio (2012, 2015, 2017), ma una volta aggiunta manualmente a csproj, verrà visualizzata in Visual Studio. Tuttavia, il percorso di destinazione non sarà modificabile tramite l'interfaccia utente.


2
Non vedo ContentWithTargetPath come opzione di azione di compilazione in VS 2015. C'è un modo per aggiungerlo?
Kim

1
Dopo aver aggiunto manualmente la voce nel file .csproj, appare come un'opzione nell'IDE. Tuttavia non riesco ancora a modificare il percorso di destinazione dall'IDE.
Kim

9
La mia unica preoccupazione è che questo non sarà più supportato con le versioni future di MSBuild / .NET / Visual Studio / Qualunque cosa, poiché l'interfaccia utente di VS2015 non mostra questa opzione o la proprietà TargetPath.
MarioDS

1
Questo funziona per me. Nessuna delle altre risposte funziona per me. Questa dovrebbe essere la risposta.
GunWanderer

1
Si noti che l'utilizzo della ContentWithTargetPathcompilazione incrementale delle interruzioni (testato su VS 2017 15.9.9)
Mads Ravn

26

Tienili dentro $(ProjectDir)\Lib, ma aggiungi quei file " Come collegamento " alla radice del tuo .csproj. Ora verranno copiati in bin \ Debug (o qualsiasi altra cartella di output) senza essere in lib.

EDIT: questa risposta è stata scritta molto tempo fa quando ContentWithTargetPath non era disponibile nelle versioni di VS / MSBuild che stavo usando. Lasciando questa risposta qui per le persone che potrebbero dover utilizzare una versione precedente di VS. Per favore smettila di commentare, sappiamo tutti che ora ci sono modi migliori.


4
Grazie ananthonline. Ho provato i tuoi passaggi ma non ha aiutato. Forse sto facendo qualcosa di sbagliato. Ecco cosa sto facendo, per favore correggi se pensi che qualcosa non sia corretto: 1. Escludi quelle DLL dal progetto ma lascia che siano in lib 2. Fai clic destro sul progetto e "Aggiungi elementi esistenti". Selezionare le DLL da lib e aggiungerle "come collegamento" 3. Fare clic con il pulsante destro del mouse sulle DLL e selezionare nuovamente "Copia sempre" in "Copia nella directory di output". 4. Pulisci e ricostruisci. Risultato: ho di nuovo ottenuto quelle DLL in \ bin \ release \ lib
OhDear

1
Pubblica uno screenshot della cartella della tua soluzione dopo averla configurata
Ani

3
Se provo ad aggiungere un collegamento a un file già nell'albero del progetto, rifiuta e invece include di nuovo il file nel progetto ...
Nyerguds

1
Come @Nyerguds, sto riscontrando che non è possibile aggiungere un collegamento a un file che è già nell'albero del progetto, quindi questa risposta non risolve la domanda.
Tore Østergaard

1
Non inonda la radice della directory del progetto in Esplora soluzioni? Con molti di questi file può essere un problema. Di solito la radice della directory di un progetto contiene già troppi file.
Alex34758

10

Se lo scopo principale è includere le DLL senza ingombrare la directory principale del progetto, un'altra soluzione consiste nello spostare le DLL in un progetto condiviso separato e aggiungerlo come riferimento nel progetto originale.

(Nota che questo post non risponde direttamente a questa domanda in quanto non preserva la cartella e la struttura del progetto, ma ho trovato utile questo approccio perché nel mio caso sono stato in grado di ristrutturare il mio progetto e perché volevo evitare alcuni dei aspetti negativi degli altri approcci qui.)

passi

  • Fai clic con il pulsante destro del mouse su Solution -> Add -> New Project -> Shared Project
  • Aggiungi le DLL a questo progetto (nella directory principale di questo progetto, non in una sottocartella "lib")
  • (Controlla che le proprietà del file DLL siano impostate correttamente, ad esempio Build Action: Contente Copy to Output Directory: Copy Always)
  • Fare clic con il pulsante destro del mouse sul progetto originale References -> Add Reference -> Shared Projects
  • Seleziona il progetto condiviso che hai creato in precedenza

La configurazione è simile a questa:

soluzione-explorer-screenshot


2
Di gran lunga la soluzione semplice ed elegante per mantenere il progetto ordinato.
Ravi Ganesh

Non sono riuscito a farlo funzionare con i file UAP e * .bin.
Matteo

7

Aggiungere i file dll come riferimento al progetto e sul set di riferimenti "Copia locale" su true.


1
Grazie Erik. Funziona perfettamente tranne che per una DLL che non sono in grado di aggiungere come riferimento. L'errore che ottengo durante l'aggiunta come riferimento è Impossibile aggiungere un riferimento a "libeay32.dll". Assicurati che il file sia accessibile e che sia un assembly o un componente COM valido.
OhDear,

7
@ MAnthony: solo gli assembly .NET o gli assembly di interoperabilità COM possono essere aggiunti come riferimenti al progetto; le DLL native non possono essere. Dovrai trovare un altro modo per copiare la DLL in \ bin \ Release.
Michael Liu,

Grazie Erik e Michael e ananthonline. Mi dispiace non posso votare a favore delle tue risposte e commenti perché non ho i punti reputazione richiesti.
OhDear,

1
Per la DLL non gestita, dovrai utilizzare il metodo suggerito di seguito.
Ani

4

Se è necessario copiare i file dalla directory Libs alla cartella principale 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>

In qualsiasi altra cartella, inclusa la cartella Libs (RecursiveDir)

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

3

In VisualStudio 2015 sembra che se le DLL che stai "aggiungendo con un collegamento" si trovano in una sottocartella dello stesso progetto , verranno automaticamente inserite in una cartella e anche l'output verrà inserito in una cartella come hai visto.

Se le DLL si trovano in un altro progetto o directory su disco non in una sottocartella del progetto , puoi "Aggiungi con un collegamento" e verranno inserite correttamente nella directory principale.


Lo stesso in VS2012. Si rifiuta di renderli un collegamento e li aggiunge semplicemente come contenuto. Alla fine, purtroppo la soluzione più semplice sembra essere quella di scaricarli nella radice del progetto.
Nyerguds

0

Un metodo alternativo consiste semplicemente nel lasciare gli elementi come tipo None. In Esplora soluzioni, fai clic su quelli che desideri distribuire e imposta la Contentproprietà True.

Nota: l'ho fatto in VS2019 e le cose possono cambiare da versione a versione.

Per farlo funzionare, ora fai clic con il pulsante destro del mouse sul tuo progetto e seleziona "Scarica progetto". Quindi fare clic con il tasto destro sul progetto scaricato e selezionare "Modifica nome_progetto.vcxproj".

Nell'editor, vai fino in fondo al file e inserisci questo target subito prima del </Project>tag finale :

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

Ora fai clic con il tasto destro sul progetto scaricato e seleziona "Ricarica progetto". Selezionare per salvare e chiudere se richiesto.

Ho anche impostato OutputDirectorysu:

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

e IntermediateDirectorya:

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

nella pagina Generale delle proprietà del progetto. Questo mette l'output in una cartella "bin" e gli intermedi in una cartella "obj" nella radice della soluzione.

Nota: $(SolutionDir)non è definito quando si esegue MSBuild dalla riga di comando. C'è un trucco che puoi usare per definirlo nella cartella in cui risiede il file .sln usando GetDirectoryNameOfFileAbove. (a sinistra come esercizio per il lettore). Inoltre, sembra che nel 2019 lo stiano gestendo correttamente sulla riga di comando comunque. Sì :) Il $(SolutionDir)contiene una barra rovesciata finale, quindi nessuno dopo di esso. I risultati di ciascuno devono avere una barra rovesciata finale.

Ora, se possiedi Pro o versioni successive, per favore non farlo ogni volta che devi creare un progetto. Sarebbe noioso. Invece, una volta che hai configurato il tuo progetto come preferisci, seleziona Project -> Export Template. Gli dai un nome e la prossima volta che vuoi creare un progetto proprio come quello, scegli quel nome nella finestra di dialogo Nuovo progetto. (Nella versione precedente, penso che fosse Files -> Export Teamplate....)


-1

Ho avuto lo stesso problema con Visual Studio 2010 / C # Project.

Per gli assembly (ovvero con l'interfaccia .NET) utilizzare la cartella "Riferimenti" sotto il progetto in Esplora soluzioni. Fare clic con il pulsante destro del mouse, scegliere "Aggiungi elemento esistente" e individuare l'assembly .dll.

I file .dll comuni possono essere inseriti in una sottocartella (come "\ lib" è stato menzionato sopra) e nelle proprietà selezionare:

  • Build Action = "HelpFiles"
  • Copia in OutputDirectory = "Se più recente"

Questo ha funzionato per me esattamente come desiderato: durante la compilazione, i file .DLL vengono copiati nella directory di output senza la sottocartella "\ lib".

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.