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 de Elmah son las siguientes:
- Alias - global
- Copiar local - verdadero
- Cultura -
- Descripción - Módulos y controladores de registro de errores (ELMAH) para ASP.NET
- Tipo de archivo - Ensamblaje
- Ruta - D: \ webs \ otherfolder \ _myPath \ __ tools \ elmah \ Elmah.dll
- Resuelto - Verdadero
- Versión de 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 al Proyecto MyBaseProject: "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 .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 manera predeterminada, aunque Visual Studio dijo "copiar local" verdadero. Cambié "copiar local" a falso - guardado - y lo configuré nuevamente como verdadero - ¡guardar!)
¿Qué le pasa a MSBuild? ¿Cómo obtengo la referencia (elmah.dll) copiada en el contenedor de MyWebProject1?
¡NO quiero agregar una acción de copia posterior a la construcción al comando de construcción posterior de cada proyecto! (¡Imagínese que muchos proyectos dependerían de MyBaseProject!)
fuente
Respuestas:
No estoy seguro de por qué es diferente al construir entre Visual Studio y MsBuild, pero esto es lo que encontré cuando me encontré con este problema en MsBuild y Visual Studio.
Explicación
Para un escenario de ejemplo, supongamos 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 a A y B. Además, el proyecto X incluye código que hace referencia al conjunto A (por ejemplo, A. SomeFunction ()). Ahora, crea 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 intenta ser inteligente y solo trae referencias al proyecto Y que detecta como requeridas por el proyecto X; lo hace para evitar la contaminación de referencia en el proyecto Y. El problema es que, dado que el proyecto X en realidad no contiene ningún código que utilice explícitamente el ensamblado B (por ejemplo, B.SomeFunction ()), VS / MSBuild no detecta que se requiere B por X, y por lo tanto no lo copia en el directorio bin del proyecto Y; solo copia los ensamblajes X y A.
Solución
Tiene dos opciones para resolver este problema, las cuales resultarán en que el ensamblado B se copie en el directorio bin del proyecto Y:
Personalmente, prefiero la opción 2 por un par de razones.
Aquí hay una muestra del "código ficticio" que normalmente agrego cuando me encuentro con esta situación.
fuente
Type dummyType = typeof(AssemblyA.AnyClass);
Console.WriteLine(dummyType.FullName);
enum
de B y supuse que la enumeración estaba en línea. Agregué código para usar directamente un tipo de B y eso no ayudó. También siempre ha sido el caso de que mi X usa tipos en A que subclases en B, por lo que no puedo entender cómo el compilador piensa que B no es requerido por X y puede ser ignorado. Esto es una locura.Solo lo trato así. Vaya a las propiedades de su referencia y haga esto:
y eso es.
Visual Studio 2010 no pone inicialmente:
<private>True</private>
en la etiqueta de referencia y establecer "copiar local" en falso hace que cree la etiqueta. Luego lo establecerá en verdadero y falso en consecuencia.fuente
<Private>true</Private>
pero parecía no tener ningún efecto en MSBuild. Al final, acabo de agregar referencias NuGet a proyectos de nivel inferior.Have you tried turning it off and on again?
, y funcionó!Si no está utilizando el ensamblado directamente en el código, Visual Studio, mientras intenta ser útil, detecta que no se utiliza y no lo incluye en la salida. No estoy seguro de por qué está viendo un comportamiento diferente entre Visual Studio y MSBuild. Puede intentar configurar la salida de compilación para el diagnóstico para ambos y comparar los resultados para ver dónde diverge.
En cuanto a su referencia de elmah.dll, si no hace referencia directa a él en el código, puede agregarlo como un elemento a su proyecto y establecer la Acción de compilación en
Content
y el Directorio Copiar a salida enAlways
.fuente
Echa un vistazo a:
Este hilo del foro de MSBuild que empecé
¡Encontrarás mi solución / solución temporal allí!
(¡MyBaseProject necesita un código que haga referencia a algunas clases (lo que sea) del elmah.dll para que elmah.dll se copie al contenedor de MyWebProject1!)
fuente
Yo tuve el mismo problema.
Compruebe si la versión de marco de su proyecto es la misma que la versión de marco de la dll que ha puesto como referencia.
En mi caso, mi cliente fue compilado usando "Framework 4 Client" y la DLL estaba en "Framework 4".
fuente
El problema que enfrentaba era que tenía un proyecto que dependía de un proyecto de biblioteca. Para construir estaba siguiendo estos pasos:
Por supuesto, eso significaba que me faltaban los archivos dll de mi biblioteca en bin y lo más importante en el archivo zip del paquete. Encontré que esto funciona perfectamente:
No tengo idea de por qué esto funciona o por qué no funcionó en primer lugar. Pero espero que eso ayude.
fuente
Acabo de tener exactamente 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 que corregí todas las referencias, todo funcionó perfectamente.
fuente
Como Alex Burtsev mencionó en un comentario, todo lo que solo se usa en un diccionario de recursos XAML, o en mi caso, todo lo que solo se usa en XAML y no en el código subyacente, MSBuild no lo considera "en uso".
Entonces, simplemente actualizar una referencia ficticia a una clase / componente en el ensamblaje en algún código detrás fue suficiente para convencer a MSBuild de que el ensamblaje estaba realmente en uso.
fuente
Cambiar el marco de destino de .NET Framework 4 Client Profile a .NET Framework 4 solucionó este problema.
Entonces, en su ejemplo: establezca el marco de destino en MyWebProject1 en .NET Framework 4
fuente
Usando el esquema de deadlydog,
Y => X => A => B ,
mi problema fue cuando construí Y, los ensamblajes (A y B, los 15) 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 de proyecto) y guardar, compilar, y A y B comenzaron a aparecer en la carpeta bin de Y.
fuente
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.
fuente
Esto requiere agregar un
.targets
archivo a su proyecto y configurarlo para que se incluya en la sección incluye del proyecto.Vea mi respuesta aquí para el procedimiento.
fuente
Hacer referencia a ensamblajes que no se usan 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 utilizando un evento posterior a la compilación o actualizando el grupo de propiedades.
Algunos ejemplos se pueden encontrar en otra publicación
fuente
Otro escenario en el que esto aparece es si está utilizando el tipo de proyecto "Sitio web" anterior 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 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 Nuget en la raíz (Paquetes), luego A. dll se incluirá, pero B.dll no.
fuente
Tuve un problema similar hoy, y esta ciertamente no es la respuesta a su pregunta. Pero me gustaría informar a todos, y posiblemente proporcionar una chispa de perspicacia.
Tengo una aplicación ASP.NET. El proceso de compilación está configurado para limpiar y luego compilar.
Tengo dos scripts de Jenkins CI . Uno para producción y otro para puesta en escena. Implementé mi aplicación en la puesta en escena y todo funcionó bien. Implementado en producción y faltaba un archivo DLL al que se hacía referencia. Este archivo DLL estaba justo en la raíz del proyecto. No en ningún repositorio de NuGet. La DLL se configuró en
do not copy
.El script de CI y la aplicación fueron iguales entre las dos implementaciones. Aún después de la limpieza e implementación en el entorno provisional, 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
bin
directorio. Ahora la parte que tardó un poco en darse cuenta. El proceso de CI no se estaba limpiando a sí mismo. 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; Verifique y asegúrese de saber qué está haciendo su servidor de compilación.
fuente
Asegúrese de que ambos proyectos estén en la misma versión .net, también verifique la propiedad local de copia, pero esto debería ser el
true
predeterminadofuente
Usando Visual Studio 2015 agregando el parámetro adicional
a la línea de comando msbuild solucionó el problema.
fuente
Me encontré con un problema muy similar. Al compilar con Visual Studio 2010, el archivo DLL se incluyó en la
bin
carpeta. Pero al compilar usando MSBuild, el archivo DLL de terceros no estaba incluido.Muy frustrante. La forma en que lo resolví fue incluir la referencia de NuGet al paquete en mi proyecto web a pesar de que no lo estoy usando directamente allí.
fuente
Incluir todos los archivos DLL a los que se hace referencia desde las referencias de su proyecto en el proyecto del sitio web no siempre es una buena idea, especialmente cuando está utilizando inyección de dependencia : su proyecto web solo desea agregar una referencia al archivo / proyecto de interfaz DLL, no cualquier DLL de implementación concreta expediente.
Porque 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 proyecto / archivo DLL de implementación en lugar de hacerlo a través de la interfaz. También ha indicado un "código duro" en su sitio web para usar la implementación.
fuente