¿Cómo hacer que Visual Studio copie un archivo DLL en el directorio de salida?

101

Tengo un proyecto de Visual Studio C ++ que se basa en un archivo DLL externo. ¿Cómo puedo hacer que Visual Studio copie este archivo DLL automáticamente en el directorio de salida (depuración / liberación) cuando construyo el proyecto?

Estera
fuente

Respuestas:

90

Utilice una acción posterior a la compilación en su proyecto y agregue los comandos para copiar la DLL infractora. La acción posterior a la compilación se escribe como un script por lotes.

Se puede hacer referencia al directorio de salida como $(OutDir). El directorio del proyecto está disponible como $(ProjDir). Intente usar parches relativos cuando corresponda, de modo que pueda copiar o mover la carpeta de su proyecto sin interrumpir la acción posterior a la compilación.

Adrien Plisson
fuente
25
También vale la pena señalar que puede configurar el evento posterior a la compilación a través de Proyecto> Propiedades> Eventos de compilación> Evento posterior a la compilación.
Phil Booth
20
ejemplo: eyeung003.blogspot.com/2009/11/…
AntonioR
36
En caso de que el enlace se rompa alguna vez: "xcopy / y" $ (ProjectDir) *. Dll "" $ (OutDir) "
ace
Cambié lo anterior a cómo uso personalmente el comando en mis instancias. Esta voluntad; copia archivos de solo lectura que son buenos con el control de fuente y crea el directorio de destino (normalmente no es necesario). -> xcopy "$ (ProjectDir) *. dll" "$ (OutDir)" / i / r / y
Come en Joes
8
Agregue la marca / d a xCopy para evitar la copia innecesaria de archivos que no han cambiado en el directorio de salida.
Zoey
43

$ (OutDir) resultó ser una ruta relativa en VS2013, así que tuve que combinarlo con $ (ProjectDir) para lograr el efecto deseado:

xcopy /y /d  "$(ProjectDir)External\*.dll" "$(ProjectDir)$(OutDir)"

Por cierto, puede depurar fácilmente los scripts agregando 'echo' al principio y observar el texto expandido en la ventana de salida de la compilación.

Nesho Neshev
fuente
3
$ (TargetDir) puede reemplazar $ (ProjectDir) $ (OutDir) porque es una combinación de ambos de todos modos.
persona27
En mi caso, sin el / d, estaba arrojando un error de Acceso denegado. Pero / d según la documentación es para la fecha. No estoy seguro de cuál es la conexión.
Ravi C
1
Agregar / d evita la sobrescritura si el archivo de origen es más antiguo o el mismo que un archivo existente. El error de acceso denegado puede ocurrir si el objetivo está bloqueado por otro proceso.
Rich Shealer
7

Los detalles en la sección de comentarios anterior no funcionaron para mí (VS 2013) al intentar copiar la dll de salida de un proyecto C ++ a la carpeta de lanzamiento y depuración de otro proyecto C # dentro de la misma solución.

Tuve que agregar la siguiente acción de compilación posterior (haga clic derecho en el proyecto que tiene una salida .dll) luego propiedades -> propiedades de configuración -> eventos de compilación -> evento posterior a la compilación -> línea de comando

ahora agregué estas dos líneas para copiar el dll de salida en las dos carpetas:

xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Release
xcopy /y $(TargetPath) $(SolutionDir)aeiscontroller\bin\Debug
SCBuergel.eth
fuente
5

(Esta respuesta solo se aplica a C #, no a C ++, lo siento, leí mal la pregunta original)

He pasado por un infierno DLL como este antes. Mi solución final fue almacenar las DLL no administradas en la DLL administrada como recursos binarios y extraerlas a una carpeta temporal cuando se inicia el programa y eliminarlas cuando se desecha.

Esto debería ser parte de la infraestructura .NET o pinvoke, ya que es muy útil ... Hace que su DLL administrado sea fácil de administrar, tanto usando Xcopy como como referencia de proyecto en una solución de Visual Studio más grande. Una vez que haga esto, no tendrá que preocuparse por los eventos posteriores a la compilación.

ACTUALIZAR:

Publiqué el código aquí en otra respuesta https://stackoverflow.com/a/11038376/364818

Mark Lakata
fuente
1
Estoy de acuerdo, debería ser parte del marco (para vincular dll estáticamente, etc.). Vale la pena señalar que almacenar el dll como un recurso y luego extraerlo en tiempo de ejecución puede causar problemas en algunos entornos corporativos (especialmente si tienen bastante software antivirus proactivo).
BrainSlugs83
1

Agregue COPY incorporado en el archivo project.csproj :

  <Project>
    ...
    <Target Name="AfterBuild">
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Debug\bin" SkipUnchangedFiles="false" />
      <Copy SourceFiles="$(ProjectDir)..\..\Lib\*.dll" DestinationFolder="$(OutDir)Release\bin" SkipUnchangedFiles="false" />
    </Target>
  </Project>
John_J
fuente
Hay un error a largo plazo en VS, use ProjectDir en lugar de SolutionDir
John_J
0
xcopy /y /d  "$(ProjectDir)External\*.dll" "$(TargetDir)"

También puede hacer referencia a una ruta relativa, el siguiente ejemplo encontrará la DLL en una carpeta ubicada un nivel por encima de la carpeta del proyecto. Si tiene varios proyectos que usan la DLL en una única solución, esto coloca la fuente de la DLL en un área común accesible cuando configura cualquiera de ellos como Proyecto de inicio.

xcopy /y /d  "$(ProjectDir)..\External\*.dll" "$(TargetDir)"

La /yopción copia sin confirmación. La /dopción comprueba si existe un archivo en el destino y si lo hace, solo se copia si el origen tiene una marca de tiempo más reciente que el destino.

Descubrí que al menos en las versiones más recientes de Visual Studio, como VS2109, $(ProjDir)no está definido y tuve que usarlo $(ProjectDir)en su lugar.

Dejar una carpeta de destino en xcopydebería ser el directorio de salida predeterminado. Eso es importante para entender que la razón por $(OutDir)sí sola no es útil.

$(OutDir), al menos en versiones recientes de Visual Studio, se define como una ruta relativa a la carpeta de salida, como bin/x86/Debug . Si lo usa solo como destino, se creará un nuevo conjunto de carpetas a partir de la carpeta de salida del proyecto. Ej … bin/x86/Debug/bin/x86/Debug. : .

Combinarlo con la carpeta del proyecto debería llevarlo al lugar adecuado. Ex:$(ProjectDir)$(OutDir) . .

sin embargo $(TargetDir) , proporcionará el directorio de salida en un solo paso.

Lista de Microsoft de macros de MSBuild para versiones actuales y anteriores de Visual Studio

Rico shealer
fuente