¿Cuáles son las diferencias entre AssemblyVersion, AssemblyFileVersion y AssemblyInformationalVersion?

Hay tres atributos de versión de ensamblaje. ¿Cuáles son las diferencias? ¿Está bien si uso AssemblyVersion e ignoro el rest?


MSDN dice:

  • AssemblyVersion :

    Especifica la versión del ensamblaje que se atribuye.

  • AssemblyFileVersion :

    Indica a un comstackdor que use un número de versión específico para el recurso de versión de archivo Win32. No es necesario que la versión del archivo Win32 sea la misma que el número de versión del ensamblaje.

  • AssemblyInformationalVersion :

    Define información de versión adicional para un manifiesto de ensamblaje.


Esta es una continuación de ¿Cuáles son las mejores prácticas para usar los Atributos de ensamblaje?

AsambleaVersión

Donde se verán otros ensambles que hacen referencia a su ensamblaje. Si este número cambia, ¡otros ensambles tienen que actualizar sus referencias a su ensamblaje! LaVisión de AssemblyVersion es obligatoria.

Yo uso el formato: major.minor . Esto daría como resultado:

 [assembly: AssemblyVersion("1.0")] 

AssemblyFileVersion

Usado para despliegue Puede boost este número para cada implementación. Es utilizado por los progtwigs de instalación. Úselo para marcar conjuntos que tengan la misma AssemblyVersion , pero se generan a partir de diferentes comstackciones.

En Windows, se puede ver en las propiedades del archivo.

Si es posible, permita que sea generado por MSBuild. AssemblyFileVersion es opcional. Si no se proporciona, se utiliza AssemblyVersion.

Utilizo el formato: major.minor.revision.build , donde utilizo la revisión para la etapa de desarrollo (Alpha, Beta, RC y RTM), paquetes de servicio y correcciones urgentes. Esto daría como resultado:

 [assembly: AssemblyFileVersion("1.0.3100.1242")] 

AssemblyInformationalVersion

La versión del producto del ensamblaje. Esta es la versión que usaría al hablar con los clientes o para mostrar en su sitio web. Esta versión puede ser una cadena, como ‘ 1.0 Release Candidate ‘.

El Análisis de código se quejará al respecto (CA2243), informado a Microsoft (no corregido en VS2013).

AssemblyInformationalVersion es opcional. Si no se proporciona, se utiliza AssemblyFileVersion.

Uso el formato: major.minor [revisión como cadena] . Esto daría como resultado:

 [assembly: AssemblyInformationalVersion("1.0 RC1")] 

El control de versiones de ensamblados en .NET puede ser una perspectiva confusa dado que actualmente existen al menos tres formas de especificar una versión para su ensamblaje.

Estos son los tres principales atributos de ensamblaje relacionados con la versión:

 // Assembly mscorlib, Version 2.0.0.0 [assembly: AssemblyFileVersion("2.0.50727.3521")] [assembly: AssemblyInformationalVersion("2.0.50727.3521")] [assembly: AssemblyVersion("2.0.0.0")] 

Por convención, las cuatro partes de la versión se denominan versión principal , versión secundaria , comstackción y revisión .

El AssemblyFileVersion está diseñado para identificar de manera única una construcción del ensamblaje individual

Normalmente, configurará manualmente Major y Minor AssemblyFileVersion para reflejar la versión del ensamblado, luego incrementará la comstackción y / o revisión cada vez que su sistema de comstackción compile el conjunto. AssemblyFileVersion debe permitirle identificar de manera única una comstackción del ensamblado, para que pueda usarlo como punto de partida para eliminar cualquier problema.

En mi proyecto actual, el servidor de comstackción codifica el número de lista de cambios de nuestro repository de control de origen en las partes de comstackción y revisión de AssemblyFileVersion. Esto nos permite mapear directamente desde un ensamblaje a su código fuente, para cualquier ensamblado generado por el servidor de comstackción (sin tener que usar tags o twigs en el control de fuente, o mantener manualmente ningún registro de las versiones publicadas).

Este número de versión se almacena en el recurso de la versión de Win32 y se puede ver cuando se visualizan las páginas de propiedades de Windows Explorer para el ensamblaje.

El CLR no se preocupa ni examina el AssemblyFileVersion.

El AssemblyInformationalVersion está destinado a representar la versión de su producto completo

El AssemblyInformationalVersion está diseñado para permitir el control de versiones coherentes de todo el producto, que puede consistir en muchos ensambles que tienen versiones independientes, quizás con políticas de versiones diferentes, y que pueden ser desarrollados por equipos diferentes.

“Por ejemplo, la versión 2.0 de un producto puede contener varios ensamblajes; uno de estos ensamblajes está marcado como versión 1.0 ya que es un ensamblaje nuevo que no se envió en la versión 1.0 del mismo producto. Normalmente, establece las partes principales y secundarias de este número de versión para representar la versión pública de su producto. Luego, incrementa las partes de comstackción y revisión cada vez que empaqueta un producto completo con todos sus ensamblajes. “- Jeffrey Richter, [CLR via C # (Second Edition)] p. 57

El CLR no se preocupa ni examina la AssemblyInformationalVersion.

La AssemblyVersion es la única versión que le importa a CLR (pero se preocupa por toda la AssemblyVersion )

AssemblyVersion es utilizado por el CLR para enlazar a ensamblajes fuertemente nombrados. Se almacena en la tabla de metadatos del manifiesto AssemblyDef del ensamblado construido y en la tabla AssemblyRef de cualquier ensamblaje que haga referencia a él.

Esto es muy importante, porque significa que cuando hace referencia a un ensamblado con un nombre fuerte, está estrechamente vinculado a una AssemblyVersion específica de ese ensamblaje. Toda la AssemblyVersion debe ser una coincidencia exacta para que la vinculación tenga éxito. Por ejemplo, si hace referencia a la versión 1.0.0.0 de un ensamblado fuertemente nombrado en tiempo de comstackción, pero solo la versión 1.0.0.1 de ese ensamblado está disponible en tiempo de ejecución, ¡el enlace fallará! (Luego tendrá que solucionar esto utilizando Redirección de encuadernación por ensamblaje ).

Confusión sobre si toda la AssemblyVersion tiene que coincidir. (Sí, lo hace)

Existe una pequeña confusión acerca de si toda la AssemblyVersion tiene que ser una coincidencia exacta para poder cargar un ensamblaje. Algunas personas tienen la falsa creencia de que solo las partes Mayor y Menor de la Versión de la Asamblea tienen que coincidir para que la vinculación tenga éxito. Esta es una suposición sensata, sin embargo, en última instancia es incorrecta (a partir de .NET 3.5), y es trivial verificar esto para su versión del CLR. Simplemente ejecuta este código de muestra .

En mi máquina, la segunda carga de ensamblaje falla, y las últimas dos líneas del registro de fusión dejan perfectamente claro por qué:

 .NET Framework Version: 2.0.50727.3521 --- Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f --- Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f Assembly binding for failed: System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040) File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f' === Pre-bind state information === LOG: User = Phoenix\Dani LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f (Fully-specified) LOG: Appbase = [...] LOG: Initial PrivatePath = NULL Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null. === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config. LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f LOG: Attempting download of new URL [...]. WRN: Comparing the assembly name resulted in the mismatch: Revision Number ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated. 

Creo que el origen de esta confusión probablemente se debe a que originalmente Microsoft tenía la intención de ser un poco más indulgente con esta concordancia estricta de AssemblyVersion completa, haciendo coincidir solo las partes de la versión Major y Minor:

“Al cargar un ensamblaje, el CLR buscará automáticamente la última versión de servicio instalada que coincida con la versión principal / secundaria del ensamblaje que se solicita.” – Jeffrey Richter, [CLR mediante C # (Segunda edición)] p. 56

Este fue el comportamiento en la versión beta 1 de la CLR 1.0, sin embargo, esta característica se eliminó antes de la versión 1.0 y no ha logrado volver a aparecer en .NET 2.0:

“Nota: Acabo de describir cómo debería pensar en los números de versión. Desafortunadamente, el CLR no trata los números de versión de esta manera. [En .NET 2.0], el CLR trata un número de versión como un valor opaco, y si un ensamblaje depende de la versión 1.2.3.4 de otro ensamblado, el CLR intenta cargar la versión 1.2.3.4 solamente (a menos que se haya implementado una redirección de enlace) ) Sin embargo, Microsoft tiene planes de cambiar el cargador de CLR en una versión futura para que cargue la última comstackción / revisión para una versión mayor / menor dada de un ensamblaje . Por ejemplo, en una versión futura del CLR, si el cargador está tratando de encontrar la versión 1.2.3.4 de un ensamblaje y existe la versión 1.2.5.0, el cargador automáticamente recogerá la última versión del servicio. Este será un cambio muy bienvenido al cargador de CLR. Por mi parte, no puedo esperar “. Jeffrey Richter, [CLR via C # (Second Edition)] p. 164 (Énfasis mío)

Como este cambio todavía no se ha implementado, creo que es seguro suponer que Microsoft se ha retrasado en esta intención, y que quizás sea demasiado tarde para cambiar esto ahora. Traté de buscar en la web para averiguar qué sucedió con estos planes, pero no pude encontrar ninguna respuesta. Todavía quería llegar al fondo del asunto.

Entonces le envié un correo electrónico a Jeff Richter y le pregunté directamente: pensé que si alguien sabía lo que sucedió, sería él.

Respondió en menos de 12 horas, un sábado por la mañana nada menos, y aclaró que la cargadora .NET 1.0 Beta 1 implementó este mecanismo de ‘avance automático’ para recoger la última comstackción y revisión disponible de un ensamblaje, pero este comportamiento fue revertido antes de .NET 1.0 enviado. Posteriormente, se intentó revivir esto, pero no apareció antes de que se enviara el CLR 2.0. Luego vino Silverlight, que tuvo prioridad para el equipo de CLR, por lo que esta funcionalidad se retrasó aún más. Mientras tanto, la mayoría de las personas que estaban en la época de CLR 1.0 Beta 1 ya han avanzado, por lo que es poco probable que esto vea la luz del día, a pesar de todo el trabajo duro que ya se le ha dedicado.

El comportamiento actual, parece, está aquí para quedarse.

También vale la pena señalar de mi discusión con Jeff que AssemblyFileVersion solo se agregó después de la eliminación del mecanismo de ‘reenvío automático’, porque después de 1.0 Beta 1, cualquier cambio en la AssemblyVersion fue un cambio radical para sus clientes, hubo entonces en ninguna parte para almacenar de forma segura su número de comstackción. AssemblyFileVersion es ese refugio seguro, ya que nunca es examinado automáticamente por el CLR. Tal vez sea más claro de esa manera, teniendo dos números de versión separados, con significados por separado, en lugar de tratar de hacer esa separación entre las partes Mayor / Menor (rompimiento) y Construir / Revisión (sin romper) de AssemblyVersion.

El resultado final: piense detenidamente sobre cuándo cambia su AssemblyVersion

La moraleja es que si está enviando ensamblajes a los que otros desarrolladores harán referencia, debe ser extremadamente cuidadoso cuando cambia (y no modifica) AssemblyVersion de esos ensamblajes. Cualquier cambio en AssemblyVersion significará que los desarrolladores de aplicaciones tendrán que volver a comstackr contra la nueva versión (para actualizar esas entradas de AssemblyRef) o usar redireccionamientos de enlace de ensamblaje para anular manualmente el enlace.

  • No cambie AssemblyVersion por una versión de mantenimiento que sea compatible con versiones anteriores.
  • Cambie AssemblyVersion por una versión que sepa que tiene cambios de última hora.

Solo eche un vistazo a los atributos de la versión en mscorlib:

 // Assembly mscorlib, Version 2.0.0.0 [assembly: AssemblyFileVersion("2.0.50727.3521")] [assembly: AssemblyInformationalVersion("2.0.50727.3521")] [assembly: AssemblyVersion("2.0.0.0")] 

Tenga en cuenta que es la AssemblyFileVersion la que contiene toda la información de servicio interesante (es la parte de revisión de esta versión que le dice en qué Service Pack se encuentra), mientras tanto, AssemblyVersion está arreglada en un viejo y aburrido 2.0.0.0. ¡Cualquier cambio en AssemblyVersion obligaría a todas las aplicaciones .NET que hacen referencia a mscorlib.dll a volverse a comstackr contra la nueva versión!

AssemblyVersion prácticamente se mantiene interna a .NET, mientras que AssemblyFileVersion es lo que ve Windows. Si va a las propiedades de un ensamblaje ubicado en un directorio y cambia a la pestaña de versión, AssemblyFileVersion es lo que verá arriba. Si ordena los archivos por versión, esto es lo que utiliza Explorer.

AssemblyInformationalVersion asigna a la “Versión del producto” y está destinado a ser puramente “utilizado por el ser humano”.

AssemblyVersion es ciertamente el más importante, pero tampoco omitiría AssemblyFileVersion . Si no proporciona AssemblyInformationalVersion , el comstackdor lo agregará quitando el fragmento de “revisión” de su número de versión y dejando major.minor.build.

AssemblyInformationalVersion y AssemblyFileVersion se muestran cuando visualiza la información de “Versión” en un archivo a través del Explorador de Windows al ver las propiedades del archivo. Estos atributos realmente se comstackn en un recurso VERSION_INFO creado por el comstackdor.

AssemblyInformationalVersion es el valor de “Versión del producto”. AssemblyFileVersion es el valor de “Versión de archivo”.

AssemblyVersion es específico de los ensamblados .NET y lo utiliza el cargador de ensamblados .NET para saber qué versión de un ensamblaje cargar / vincular en tiempo de ejecución.

Fuera de estos, el único que absolutamente requiere .NET es el atributo AssemblyVersion . Desafortunadamente también puede causar la mayoría de los problemas cuando cambia indiscriminadamente, especialmente si usted está dando un nombre fuerte a sus ensamblajes.

Vale la pena mencionar algunas otras cosas:

1) Como se muestra en el cuadro de diálogo Propiedades del Explorador de Windows para el archivo de ensamblaje generado, hay dos lugares llamados “Versión de archivo”. El que se ve en el encabezado del diálogo muestra AssemblyVersion, no AssemblyFileVersion.

En la sección Información de otra versión, hay otro elemento llamado “Versión de archivo”. Aquí es donde puede ver lo que se ingresó como AssemblyFileVersion.

2) AssemblyFileVersion es solo texto sin formato. No tiene que ajustarse a las restricciones del esquema de numeración que realiza AssemblyVersion ( <65K, por ejemplo). Puede ser 3.2. . , si lo desea. Tu sistema de comstackción tendrá que completar los tokens.

Además, no está sujeto al reemplazo de comodín que AssemblyVersion. Si solo tiene un valor de “3.0.1. *” En AssemblyInfo.cs, eso es exactamente lo que se mostrará en el elemento Otra versión información-> Versión de archivo.

3) No sé el impacto en el instalador de usar algo más que números de versión de archivo numérico.

Para mantener actualizada esta pregunta, cabe destacar que NuGet utiliza AssemblyInformationalVersion y refleja la versión del paquete, incluido cualquier sufijo de prelanzamiento.

Por ejemplo, una AssemblyVersion de 1.0.3. * Empaquetada con asp.net core dotnet-cli

 dotnet pack --version-suffix ci-7 src/MyProject 

Produce un paquete con la versión 1.0.3-ci-7 que puede inspeccionar con reflexión utilizando:

 CustomAttributeExtensions.GetCustomAttribute(asm); 

Cuando se cambia la AssemblyVersion de un conjunto, si tiene un nombre fuerte, los ensamblados de referencia deben volver a comstackrse, de lo contrario, el ensamblaje no se carga. Si no tiene un nombre seguro, si no se agrega explícitamente al archivo de proyecto, no se copiará en el directorio de salida cuando se compile, por lo que puede omitir los ensamblados, especialmente después de limpiar el directorio de salida.