visual studio - visual - MSBuild no copia las referencias(archivos DLL) si usa las dependencias del proyecto en la solución
vscode task variables (17)
Tengo cuatro proyectos en mi solución de Visual Studio (todos dirigidos a .NET 3.5); para mi problema, solo estos dos son importantes:
- MyBaseProject <: esta biblioteca de clases hace referencia a un archivo DLL de terceros (elmah.dll)
- MyWebProject1 <- este proyecto de aplicación web tiene una referencia a MyBaseProject
Agregué la referencia elmah.dll a MyBaseProject en Visual studio 2008 haciendo clic en "Agregar referencia ..." → pestaña "Examinar" → seleccionando "elmah.dll".
Las propiedades de la referencia Elmah son las siguientes:
- Alias - globales
- Copia local - verdadero
- Cultura -
- Descripción - Módulos y controladores de registro de errores (ELMAH) para ASP.NET
- Tipo de archivo - Asamblea
- Ruta: D: / webs / otherfolder / _myPath / __ tools / elmah / Elmah.dll
- Resuelto - Verdadero
- Versión en tiempo de ejecución - v2.0.50727
- Versión especificada - falso
- Nombre fuerte - falso
- Versión - 1.0.11211.0
En MyWebProject1 agregué la referencia a Project MyBaseProject por: "Agregar referencia ..." → pestaña "Proyectos" → seleccionando "MyBaseProject". Las propiedades de esta referencia son las mismas, excepto los siguientes miembros:
- Descripción -
- Ruta: D: / webs / CMS / MyBaseProject / bin / Debug / MyBaseProject.dll
- Versión - 1.0.0.0
Si ejecuto la compilación en Visual Studio, el archivo elmah.dll se copia en el directorio bin de MyWebProject1 , junto con MyBaseProject.dll.
Sin embargo, si limpio y ejecuto MSBuild para la solución (a través de D: / webs / CMS> C: / WINDOWS / Microsoft.NET / Framework / v3.5 / MSBuild.exe / t: ReBuild / p: Configuration = Debug MyProject.sln ) falta el elmah.dll en el directorio bin de MyWebProject1, aunque la compilación en sí no contiene advertencias ni errores.
Ya me aseguré de que el archivo .csproj de MyBaseProject contenga el elemento privado con el valor "verdadero" (que debería ser un alias para " copiar local " en Visual Studio):
<Reference Include="Elmah, Version=1.0.11211.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>../mypath/__tools/elmah/Elmah.dll</HintPath>
**<Private>true</Private>**
</Reference>
(La etiqueta privada no apareció en el xml de .csproj de forma predeterminada, aunque Visual Studio dijo "true local" true. Cambié "copy local" a falso - guardado - y lo puse de nuevo en verdadero - ¡guarda!)
¿Qué está mal con MSBuild? ¿Cómo obtengo la referencia (elmah.dll) copiada en el contenedor de MyWebProject1?
¡NO quiero agregar una acción de copia de postbuild al comando postbuild de cada proyecto! (¡Imagina que tendría muchos proyectos que dependen de MyBaseProject!)
Acabo de encontrar un problema muy similar. Al compilar con Visual Studio 2010, el archivo DLL se incluyó en la carpeta bin
. Pero al compilar con MSBuild no se incluyó el archivo DLL de terceros.
Muy frustrante. La forma en que lo resolví fue incluir la referencia NuGet al paquete en mi proyecto web, aunque no lo esté usando directamente allí.
Acabo de tener el mismo problema y resultó ser el hecho de que 2 proyectos en la misma solución hacían referencia a una versión diferente de la biblioteca de terceros.
Una vez corregidas todas las referencias todo funcionó perfectamente.
Cambiar el marco de destino de .NET Framework 4 Client Profile a .NET Framework 4 solucionó este problema.
En su ejemplo, establezca el marco de destino en MyWebProject1 en .NET Framework 4
Como Alex Burtsev mencionó en un comentario cualquier cosa que solo se use en un diccionario de recursos de XAML, o en mi caso, cualquier cosa que solo se use en XAML y no en el código anterior, no se considera que esté en uso por MSBuild.
Así que simplemente agregar una referencia ficticia a una clase / componente en el ensamblaje en algún código posterior fue suficiente para convencer a MSBuild de que el ensamblaje estaba realmente en uso.
Echa un vistazo a:
Este hilo del foro de MSBuild comencé
¡Encontrarás mi solución / solución temporal allí!
(MyBaseProject necesita algún código que haga referencia a algunas clases (lo que sea) del elmah.dll para que elmah.dll se copie a la bandeja de MyWebProject1)
El problema al que me enfrentaba era que tengo un proyecto que depende de un proyecto de biblioteca. Para construir estaba siguiendo estos pasos:
msbuild.exe myproject.vbproj /T:Rebuild
msbuild.exe myproject.vbproj /T:Package
Eso, por supuesto, significaba que me faltaban los archivos dll de mi biblioteca en el contenedor y, lo más importante, en el archivo zip del paquete. Encontré que esto funciona perfectamente:
msbuild.exe myproject.vbproj /T:Rebuild;Package
No tengo ni idea de por qué este trabajo o por qué no funcionó en primer lugar. Pero espero que ayude.
Esto requiere agregar un archivo .targets
a su proyecto y configurarlo para que se incluya en la sección de inclusión del proyecto.
Vea mi respuesta aquí para el procedimiento.
Hacer referencia a los ensamblajes que no se utilizan durante la compilación no es la práctica correcta. Debe aumentar su archivo de compilación para que copie los archivos adicionales. Ya sea mediante un evento de compilación posterior o actualizando el grupo de propiedades.
Algunos ejemplos se pueden encontrar en otras publicaciones.
Incluir todos los archivos DLL a los que se hace referencia desde su proyecto, las referencias en el proyecto del sitio web no siempre es una buena idea, especialmente cuando está utilizando la inyección de dependencia : su proyecto web solo desea agregar una referencia a la interfaz archivo / proyecto DLL, no a cualquier DLL de implementación concreta expediente.
Debido a que si agrega una referencia directamente a un archivo / proyecto DLL de implementación, no puede evitar que su desarrollador llame a un "nuevo" en clases concretas del archivo / proyecto DLL de implementación en lugar de hacerlo a través de la interfaz. También ha indicado un "código" en su sitio web para usar la implementación.
No estoy seguro de por qué es diferente cuando se construye entre Visual Studio y MsBuild, pero aquí es lo que he encontrado cuando he encontrado este problema en MsBuild y Visual Studio.
Explicación
Para un caso de ejemplo, digamos que tenemos el proyecto X, el conjunto A y el conjunto B. El conjunto A hace referencia al conjunto B, por lo que el proyecto X incluye una referencia tanto a A como a B. Además, el proyecto X incluye un código que hace referencia al conjunto A (por ejemplo, A. SomeFunction ()). Ahora, creas un nuevo proyecto Y que hace referencia al proyecto X.
Entonces, la cadena de dependencia se ve así: Y => X => A => B
Visual Studio / MSBuild trata de ser inteligente y solo trae referencias al proyecto Y que detecta como requerido por el proyecto X; hace esto para evitar la contaminación de referencia en el proyecto Y. El problema es que, dado que el proyecto X no contiene ningún código que use explícitamente el conjunto B (por ejemplo, B.SomeFunction ()), VS / MSBuild no detecta que B es necesario por X, y por lo tanto no lo copia en el directorio bin del proyecto Y; solo copia las asambleas X y A.
Solución
Tiene dos opciones para resolver este problema, las cuales darán como resultado que el ensamblaje B se copie al directorio bin del proyecto Y:
- Agregue una referencia al conjunto B en el proyecto Y.
- Agregue código falso a un archivo en el proyecto X que usa el ensamblaje B.
Personalmente prefiero la opción 2 por un par de razones.
- Si agrega otro proyecto en el futuro que hace referencia al proyecto X, no tendrá que recordar incluir también una referencia al conjunto B (como tendría que ver con la opción 1).
- Puede tener comentarios explícitos que indiquen por qué el código ficticio debe estar allí y no eliminarlo. Entonces, si alguien elimina el código por accidente (por ejemplo, con una herramienta de refactoría que busca el código no utilizado), puede ver fácilmente desde el control de la fuente que se necesita el código y restaurarlo. Si usa la opción 1 y alguien usa una herramienta de refactorización para limpiar las referencias no utilizadas, no tiene ningún comentario; verá que se eliminó una referencia del archivo .csproj.
Aquí hay una muestra del "código ficticio" que normalmente agrego cuando me encuentro con esta situación.
// DO NOT DELETE THIS CODE UNLESS WE NO LONGER REQUIRE ASSEMBLY A!!!
private void DummyFunctionToMakeSureReferencesGetCopiedProperly_DO_NOT_DELETE_THIS_CODE()
{
// Assembly A is used by this file, and that assembly depends on assembly B,
// but this project does not have any code that explicitly references assembly B. Therefore, when another project references
// this project, this project''s assembly and the assembly A get copied to the project''s bin directory, but not
// assembly B. So in order to get the required assembly B copied over, we add some dummy code here (that never
// gets called) that references assembly B; this will flag VS/MSBuild to copy the required assembly B over as well.
var dummyType = typeof(B.SomeClass);
Console.WriteLine(dummyType.FullName);
}
Otro escenario en el que se muestra esto es si está utilizando el tipo de proyecto anterior "Sitio web" en Visual Studio. Para ese tipo de proyecto, no puede hacer referencia a .dlls que están fuera de su propia estructura de directorios (carpeta actual y hacia abajo). Entonces, en la respuesta anterior, digamos que la estructura de su directorio se ve así:
Donde ProjectX y ProjectY son directorios padre / hijo, y ProjectX hace referencia a A.dll, que a su vez hace referencia a B.dll, y B.dll está fuera de la estructura del directorio, como en un paquete de Nuget en la raíz (Paquetes), luego A. Se incluirá dll, pero no B.dll.
Si no está utilizando el ensamblaje directamente en el código, Visual Studio mientras intenta ser útil, detecta que no se usa y no lo incluye en la salida. No estoy seguro de por qué estás viendo un comportamiento diferente entre Visual Studio y MSBuild. Puede intentar establecer la salida de compilación para diagnosticar ambos y comparar los resultados, ver dónde se desvía.
En cuanto a su referencia a elmah.dll, si no hace referencia a ella directamente en el código, puede agregarlo como un elemento a su proyecto y configurar la Acción de compilación en Content
y la Copia en el Directorio de resultados en Always
.
Solo trato con esto de esta manera. Ve a las propiedades de tu referencia y haz esto:
Set "Copy local = false"
Save
Set "Copy local = true"
Save
y eso es.
Visual Studio 2010 no coloca inicialmente: <private>True</private>
en la etiqueta de referencia y la configuración de "copiar local" en falso hace que cree la etiqueta. Después, se ajustará a verdadero y falso en consecuencia.
Tuve el mismo problema y el dll era una referencia cargada dinámicamente. Para resolver el problema, he agregado un "uso" con el espacio de nombres de la dll. Ahora el dll se copia en la carpeta de salida.
Tuve un problema similar hoy, y ciertamente esta no es la respuesta a tu pregunta. Pero me gustaría informar a todos, y posiblemente proporcionar una chispa de visión.
Tengo una aplicación ASP.NET. El proceso de construcción se establece para limpiar y luego construir.
Tengo dos scripts Jenkins CI . Uno para producción y otro para puesta en escena. Desplegué mi aplicación a la puesta en escena y todo funcionó bien. Se implementó en producción y faltaba un archivo DLL al que se hacía referencia. Este archivo DLL estaba en la raíz del proyecto. No en ningún repositorio de NuGet. La DLL fue configurada para do not copy
.
El script de CI y la aplicación fueron los mismos entre las dos implementaciones. Aún después de la limpieza e implementación en el entorno de prueba, el archivo DLL se reemplazó en la ubicación de implementación de la aplicación ASP.NET ( bin/
). Este no fue el caso para el entorno de producción.
Resulta que, en una rama de prueba, había agregado un paso al proceso de compilación para copiar este archivo DLL en el directorio bin
. Ahora la parte que tomó un poco de tiempo para averiguar. El proceso de CI no se estaba limpiando solo. La DLL se dejó en el directorio de trabajo y se empaquetó accidentalmente con el archivo .zip de ASP.NET. La rama de producción nunca tuvo el archivo DLL copiado de la misma manera y nunca lo implementó accidentalmente.
TLDR; Comprueba y asegúrate de saber qué está haciendo tu servidor de compilación.
Usando el esquema de deadlydog,
Y => X => A => B ,
mi problema fue cuando construí Y, los ensamblajes (A y B, los 15 de ellos) de X no aparecían en la carpeta bin de Y.
Lo resolví eliminando la referencia X de Y, guardar, compilar, luego volver a agregar la referencia X (una referencia del proyecto), y guardar, compilar, y A y B comenzaron a aparecer en la carpeta bin de Y.
Yo tuve el mismo problema.
Verifique si la versión de marco de su proyecto es la misma que la versión de marco de la dll que puso en referencia.
En mi caso, mi cliente se compiló usando "Framework 4 Client" y la DLL estaba en "Framework 4".