Visual Studio: ¿Cómo "Copiar al directorio de salida" sin copiar la estructura de carpetas?

111

Tengo algunos archivos dll en la carpeta \ lib de mi carpeta de proyecto. En la página de propiedades de dll, he seleccionado "Acción de compilación" como "Contenido" y "Copiar al directorio de salida" como "Copiar siempre".

Después de la compilación, en realidad estoy copiando el dll, pero están dentro de \ bin \ Release \ lib y no en \ bin \ Release.

¿Hay alguna forma de copiar archivos dll en \ bin \ Release (y no en \ bin \ Release \ lib) sin escribir un script posterior a la compilación o recurrir a nant, etc.?

Oh querido
fuente

Respuestas:

255

en lugar de <Content>usar <ContentWithTargetPath>y especificar la ruta de destino, así:

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

Tenga en cuenta que es posible que esta entrada no sea visible desde Visual Studio (2012, 2015, 2017), pero una vez agregada manualmente al csproj, aparecerá en Visual Studio. Sin embargo, la ruta de destino no se podrá editar a través de la interfaz de usuario.

Daniel Zeitlin
fuente
2
No veo ContentWithTargetPath como una opción de Acción de compilación en VS 2015. ¿Hay alguna forma de agregarlo?
Kim
1
Una vez que agregué la entrada manualmente en el archivo .csproj, aparece como una opción en el IDE. Sin embargo, todavía no puedo editar la ruta de destino desde el IDE.
Kim
9
Mi única preocupación es que esto no será compatible con versiones futuras de MSBuild / .NET / Visual Studio / Whatever, ya que la interfaz de usuario de VS2015 no muestra esta opción ni la propiedad TargetPath.
MarioDS
1
Esto funciona para mi. Ninguna de las otras respuestas me funciona. Esta debería ser la respuesta.
GunWanderer
1
Tenga en cuenta que el uso de ContentWithTargetPathrupturas de compilación incremental (probado en VS 2017 15.9.9)
Mads Ravn
26

Guárdelos $(ProjectDir)\Lib, pero agregue esos archivos " Como un vínculo " a la raíz de su .csproj. Ahora se copiarán en bin \ Debug (o cualquier otra carpeta de salida) sin estar en lib.

EDITAR: Esta respuesta se escribió hace mucho tiempo cuando ContentWithTargetPath no estaba disponible en las versiones de VS / MSBuild que estaba usando. Dejando esta respuesta aquí para las personas que podrían tener que usar una versión anterior de VS. Deje de comentar sobre esto, todos sabemos que ahora hay mejores formas.

Y yo
fuente
4
Gracias ananthonline. Probé tus pasos pero no sirvió de nada. Puede que esté haciendo algo mal. Esto es lo que estoy haciendo, corríjalo si cree que algo es incorrecto: 1. Excluya esos dlls del proyecto pero déjelos en la biblioteca 2. Haga clic derecho en el proyecto y "Agregar elementos existentes". Seleccione las DLL de lib y agréguelas "como enlace" 3. Haga clic derecho en las DLL y seleccione nuevamente "Copiar siempre" en "Copiar al directorio de salida". 4. Limpiar y reconstruir. Resultado: nuevamente obtuve esos dlls en \ bin \ release \ lib
OhDear
1
Publique una captura de pantalla de la carpeta de su solución después de configurarla
Ani
3
Si trato de agregar un enlace a un archivo que ya está en el árbol del proyecto, se niega y, en su lugar, solo incluye el archivo en el proyecto nuevamente ...
Nyerguds
1
Al igual que @Nyerguds, estoy experimentando que no puede agregar un enlace a un archivo que ya está en el árbol del proyecto, por lo que esta respuesta no resuelve la pregunta.
Tore Østergaard
1
¿No inunda la raíz del directorio del proyecto en el Explorador de soluciones? Con muchos archivos de este tipo, puede ser un problema. Por lo general, la raíz de un directorio de proyecto ya contiene demasiados archivos.
Alex34758
10

Si su intención principal es incluir archivos DLL sin saturar el directorio raíz del proyecto, otra solución es mover los archivos DLL a un proyecto compartido separado y agregar esto como referencia en el proyecto original.

(Tenga en cuenta que esta publicación no responde directamente a esta pregunta ya que no conserva la estructura de la carpeta y el proyecto, pero encontré este enfoque útil porque pude reestructurar mi proyecto en mi caso y porque quería evitar algunos de los desventajas de los otros enfoques aquí).

Pasos

  • Haga clic derecho en su Solution -> Add -> New Project -> Shared Project
  • Agregue las DLL a este proyecto (en el directorio raíz de este proyecto, no en una subcarpeta "lib")
  • (Compruebe que las propiedades del archivo DLL estén configuradas correctamente, por ejemplo, Build Action: Contenty Copy to Output Directory: Copy Always)
  • Haga clic derecho en el proyecto original References -> Add Reference -> Shared Projects
  • Seleccione el proyecto compartido que creó anteriormente

La configuración se ve así:

captura de pantalla del explorador de soluciones

hijo
fuente
2
Con mucho, la solución simple y elegante para mantener el proyecto ordenado.
Ravi Ganesh
No pude hacer que funcione con archivos UAP y * .bin.
Matteo
7

Agregue los archivos dll como referencia al proyecto y en el conjunto de referencia "Copiar local" a verdadero.

erik_nw
fuente
1
Gracias Erik. Eso funciona perfectamente, excepto por un dll que no puedo agregar como referencia. El error que obtengo al agregar como referencia es No se pudo agregar una referencia a 'libeay32.dll'. Asegúrese de que el archivo sea accesible y de que sea un ensamblado o componente COM válido.
OhDear
7
@MAnthony: solo se pueden agregar ensamblados .NET o ensamblados de interoperabilidad COM como referencias de proyecto; Las DLL nativas no pueden serlo. Deberá encontrar alguna otra forma de copiar la DLL en \ bin \ Release.
Michael Liu
Gracias Erik y Michael y ananthonline. Lo siento, no puedo votar a favor de sus respuestas y comentarios ya que no tengo los puntos de reputación requeridos.
OhDear
1
Para la DLL no administrada, deberá utilizar el método que sugerí a continuación.
Ani
4

Si necesita copiar archivos del directorio Libs a la carpeta raíz 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>

A cualquier otra carpeta, incluida la carpeta Libs (RecursiveDir)

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

En VisualStudio 2015 parece que si los dlls que está 'agregando con un enlace' están en una subcarpeta de ese mismo proyecto , se colocarán automáticamente en una carpeta y la salida también se colocará en una carpeta como la que vio.

Si las DLL están en otro proyecto o directorio en el disco que no está en una subcarpeta del proyecto , puede 'Agregar con un enlace', y se colocarán en el directorio raíz sin problemas.

DefenestraciónDía
fuente
Lo mismo en VS2012. Se niega a convertirlos en un enlace y simplemente los agrega como contenido. Al final, lamentablemente, la solución más fácil parece ser volcarlos en la raíz del proyecto.
Nyerguds
0

Un método alternativo es simplemente dejar los elementos como tipo None. En el explorador de soluciones, haga clic en las que desea implementar y establezca la Contentpropiedad en True.

Nota: Hice esto en VS2019 y las cosas pueden cambiar de una versión a otra.

Para que esto funcione, ahora haga clic derecho en su proyecto y seleccione "Descargar proyecto". Luego haga clic derecho en el proyecto descargado y seleccione "Editar nombre_proyecto.vcxproj".

En el editor, vaya hasta el final del archivo e inserte este destino justo antes de la </Project>etiqueta final :

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

Ahora haga clic derecho en el proyecto descargado y seleccione "Recargar proyecto". Seleccione para guardar y cerrar si se le solicita.

También configuré el OutputDirectorypara:

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

y el IntermediateDirectorya:

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

en la página General de propiedades del proyecto. Esto coloca la salida en una carpeta "bin" y los intermedios en una carpeta "obj" en la raíz de su solución.

Nota: $(SolutionDir)no se define cuando ejecuta MSBuild desde la línea de comandos. Hay un truco que puede usar para definir eso en la carpeta donde vive el archivo .sln usando GetDirectoryNameOfFileAbove. (dejado como ejercicio para el lector). Además, parece que en 2019 lo están manejando correctamente en la línea de comandos de todos modos. Sí :) El$(SolutionDir) contiene una barra diagonal inversa, por lo tanto, no después de ella. Los resultados de cada uno deben tener una barra invertida al final.

Ahora, si posee Pro o superior, no haga esto cada vez que necesite crear un proyecto. Eso sería tonto. En cambio, una vez que haya configurado su proyecto de la manera que le gusta, seleccione Project -> Export Template. Le da un nombre y la próxima vez que desee crear un proyecto como ese, simplemente elija ese nombre en el cuadro de diálogo Nuevo proyecto. (En la versión anterior, creo que esto fue así Files -> Export Teamplate...).

ChuckEng
fuente
-1

Tuve el mismo problema con Visual Studio 2010 / C # Project.

Para ensamblajes (es decir, que tengan la interfaz .NET) use la carpeta "Referencias" debajo de su proyecto en el Explorador de soluciones. Haz clic derecho, elige "Agregar elemento existente" y localiza tu ensamblaje .dll.

Los archivos .dll comunes se pueden colocar en una subcarpeta (como se mencionó anteriormente "\ lib") y en las propiedades seleccione:

  • Build Action = "HelpFiles"
  • Copiar a OutputDirectory = "Si es más reciente"

Esto funcionó para mí exactamente como lo deseaba: durante la compilación, los .DLL se copian en el directorio de salida sin la subcarpeta "\ lib".

Petr Hendl
fuente