it-swarm-pt.tech

Quais são as diferenças entre AssemblyVersion, AssemblyFileVersion e AssemblyInformationalVersion?

Existem três atributos da versão Assembly. Quais são as diferenças? Tudo bem se eu usar AssemblyVersion e ignorar o resto?


MSDN diz:

  • AssemblyVersion :

    Especifica a versão do assembly sendo atribuído.

  • AssemblyFileVersion :

    Instrui um compilador para usar um número de versão específico para o recurso de versão do arquivo Win32. Não é necessário que a versão do arquivo Win32 seja igual ao número da versão do Assembly.

  • AssemblyInformationalVersion :

    Define informações de versão adicionais para um manifesto de assembly.


Este é um follow-up para Quais são as melhores práticas para usar Atributos de Montagem?

824
Jakub Šturc

AssemblyVersion

Onde outras assembléias que fazem referência a sua Assembléia vão olhar. Se esse número for alterado, outras montagens terão que atualizar suas referências à sua montagem! O AssemblyVersion é obrigatório.

Eu uso o formato: major.minor . Isso resultaria em:

[Assembly: AssemblyVersion("1.0")]

AssemblyFileVersion

Usado para implantação. Você pode aumentar esse número para cada implantação. É usado por programas de instalação. Use-o para marcar assemblies que tenham o mesmo AssemblyVersion, mas sejam gerados a partir de diferentes construções.

No Windows, pode ser visualizado nas propriedades do arquivo.

Se possível, deixe que seja gerado pelo MSBuild. O AssemblyFileVersion é opcional. Se não for fornecido, o AssemblyVersion é usado.

Eu uso o formato: major.minor.revision.build , onde uso revisão para estágio de desenvolvimento (Alpha, Beta, RC e RTM), service packs e hot fixes. Isso resultaria em:

[Assembly: AssemblyFileVersion("1.0.3100.1242")]

AssemblyInformationalVersion

A versão do produto da montagem. Essa é a versão que você usaria ao conversar com clientes ou para exibição em seu website. Esta versão pode ser uma string, como ' 1.0 Release Candidate '.

A análise de código irá reclamar sobre isso (CA2243) - reportado à Microsoft (não corrigido no VS2013).

O AssemblyInformationalVersion é opcional. Se não for fornecido, o AssemblyFileVersion é usado.

Eu uso o formato: major.minor [revisão como string] . Isso resultaria em:

[Assembly: AssemblyInformationalVersion("1.0 RC1")]
871
Rémy van Duijkeren

O controle de versão de assemblies no .NET pode ser uma perspectiva confusa, pois atualmente existem pelo menos três maneiras de especificar uma versão para o seu Assembly.

Aqui estão os três atributos principais do Assembly relacionados à versão:

// 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 convenção, as quatro partes da versão são chamadas de Versão Principal , Versão Secundária , Build , e Revisão .

O AssemblyFileVersion destina-se a identificar exclusivamente uma compilação da Assembly individual

Normalmente, você define manualmente a versão maior e menor do arquivo de montagem para refletir a versão do conjunto e, em seguida, incrementa o build e/ou a revisão toda vez que o sistema de compilação compila o assembly. O AssemblyFileVersion deve permitir que você identifique exclusivamente uma compilação do Assembly, para que você possa usá-lo como ponto de partida para depurar quaisquer problemas.

No meu projeto atual, temos o servidor de compilação que codifica o número da lista de alterações de nosso repositório de controle de origem nas partes de Construção e Revisão do AssemblyFileVersion. Isso nos permite mapear diretamente de um Assembly para seu código-fonte, para qualquer Assembly gerado pelo servidor de compilação (sem ter que usar rótulos ou ramificações no controle de origem ou manter manualmente quaisquer registros de versões liberadas).

Este número de versão é armazenado no recurso de versão do Win32 e pode ser visto ao exibir as páginas de propriedade do Windows Explorer para o Assembly.

O CLR não se preocupa nem examina o AssemblyFileVersion

O AssemblyInformationalVersion destina-se a representar a versão de todo o seu produto

A AssemblyInformationalVersion destina-se a permitir a versão coerente de todo o produto, que pode consistir em muitos conjuntos de versões independentes, talvez com diferentes políticas de controle de versão, e potencialmente desenvolvidos por equipes diferentes.

“Por exemplo, a versão 2.0 de um produto pode conter vários conjuntos; Um desses conjuntos está marcado como versão 1.0, pois é um novo conjunto que não foi enviado na versão 1.0 do mesmo produto. Normalmente, você define as partes principais e secundárias deste número de versão para representar a versão pública de seu produto. Então você incrementa as partes de compilação e revisão toda vez que você empacota um produto completo com todas as suas montagens. ”- Jeffrey Richter, [CLR via C # (Segunda Edição)] p. 57

O CLR não se preocupa nem examina a versão AssemblyInformationalVersion

O AssemblyVersion é a única versão com a qual o CLR se preocupa (mas se importa com o AssemblyVersion inteiro)

O AssemblyVersion é usado pelo CLR para vincular a assemblies com nomes fortes. Ele é armazenado na tabela de metadados do manifesto AssemblyDef do Assembly construído e na tabela AssemblyRef de qualquer Assembly que faça referência a ele.

Isso é muito importante, porque significa que, quando você faz referência a um Assembly com um nome forte, você está intimamente ligado a uma AssemblyVersion específica desse Assembly. A AssemblyVersion inteira deve ser uma correspondência exata para que a ligação seja bem-sucedida. Por exemplo, se você referenciar a versão 1.0.0.0 de um Assembly com nome forte no tempo de compilação, mas apenas a versão 1.0.0.1 desse Assembly estiver disponível no tempo de execução, a ligação falhará! (Você terá que contornar isso usando Redirecionamento de Ligação de Montagem .)

Confusão sobre se o AssemblyVersion inteiro deve corresponder. (Sim.)

Há uma pequena confusão sobre se a AssemblyVersion inteira precisa ser uma correspondência exata para que um Assembly seja carregado. Algumas pessoas estão sob a falsa crença de que somente as partes Maior e Menor da AssemblyVersion precisam corresponder para que a vinculação seja bem-sucedida. Esta é uma suposição sensata, no entanto, é basicamente incorreta (como no .NET 3.5), e é trivial verificar isso para sua versão do CLR. Apenas execute este código de exemplo .

Na minha máquina, o segundo carregamento da montagem falha e as duas últimas linhas do log de fusão deixam claro o motivo:

.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.

Eu acho que a fonte dessa confusão é provavelmente porque a Microsoft originalmente pretendia ser um pouco mais tolerante com essa correspondência estrita da AssemblyVersion completa, correspondendo apenas às partes da versão Major e Minor:

“Ao carregar um Assembly, o CLR irá encontrar automaticamente a última versão de serviço instalada que corresponde à versão principal/secundária do Assembly sendo solicitada.” - Jeffrey Richter, [CLR via C # (Second Edition)] p. 56

Esse foi o comportamento na versão Beta 1 do CLR 1.0, mas esse recurso foi removido antes do lançamento 1.0 e não conseguiu ressurgir no .NET 2.0:

“Nota: acabei de descrever como você deve pensar nos números das versões. Infelizmente, o CLR não trata números de versão dessa maneira. [No .NET 2.0], o CLR trata um número de versão como um valor opaco, e se um Assembly depende da versão 1.2.3.4 de outro Assembly, o CLR tenta carregar somente a versão 1.2.3.4 (a menos que um redirecionamento de ligação esteja em vigor) ). No entanto, a Microsoft tem planos para alterar o carregador do CLR em uma versão futura para que ele carregue a compilação/revisão mais recente para uma determinada versão principal/secundária de um Assembly . Por exemplo, em uma versão futura do CLR, se o carregador estiver tentando encontrar a versão 1.2.3.4 de um Assembly e a versão 1.2.5.0 existir, o carregador selecionará automaticamente a versão de serviço mais recente. Essa será uma mudança bem-vinda para o carregador do CLR - eu não posso esperar. ”- Jeffrey Richter, [CLR via C # (segunda edição)] p. 164 (ênfase minha)

Como essa mudança ainda não foi implementada, acho que é seguro presumir que a Microsoft voltou atrás nessa intenção e talvez seja tarde demais para mudar isso agora. Tentei pesquisar na Web para descobrir o que aconteceu com esses planos, mas não consegui encontrar nenhuma resposta. Eu ainda queria chegar ao fundo disso.

Então, eu enviei um e-mail para Jeff Richter e perguntei a ele diretamente - imaginei que se alguém soubesse o que aconteceu, seria ele.

Ele respondeu no prazo de 12 horas, em um sábado de manhã e esclareceu que o carregador do .NET 1.0 Beta 1 implementou esse mecanismo de 'roll-forward' automático de pegar o último build e revisão de uma Assembly disponível, mas esse comportamento foi revertido antes do envio do .NET 1.0. Mais tarde, ele pretendia reviver isso, mas não chegou antes do lançamento do CLR 2.0. Depois veio o Silverlight, que teve prioridade para a equipe do CLR, então essa funcionalidade ficou ainda mais atrasada. Enquanto isso, a maioria das pessoas que estavam por perto desde a época do CLR 1.0 Beta 1 já se mudaram, então é improvável que isso tenha a luz do dia, apesar de todo o trabalho árduo que já foi colocado nele.

O comportamento atual parece estar aqui para ficar.

Também é digno de nota da minha discussão com Jeff que o AssemblyFileVersion foi adicionado somente após a remoção do mecanismo 'roll-forward' automático - porque depois do 1.0 Beta 1, qualquer alteração na AssemblyVersion era uma alteração importante para seus clientes, nenhum lugar para armazenar com segurança o seu número de compilação. O AssemblyFileVersion é o refúgio seguro, pois nunca é examinado automaticamente pelo CLR. Talvez seja mais claro assim, ter dois números de versão separados, com significados separados, em vez de tentar fazer essa separação entre as partes Major/Minor (quebra) e Build/Revision (não quebra) da AssemblyVersion.

A linha inferior: Pense cuidadosamente sobre quando você muda seu AssemblyVersion

A moral é que, se você estiver enviando conjuntos para os quais outros desenvolvedores farão referência, você precisa ser extremamente cuidadoso quando fizer (e não) alterar a AssemblyVersion desses assemblies. Qualquer alteração no AssemblyVersion significará que os desenvolvedores de aplicativos terão que recompilar novamente a nova versão (para atualizar essas entradas do AssemblyRef) ou usar os redirecionamentos de ligação do Assembly para substituir manualmente a ligação.

  • Não altere o AssemblyVersion para uma liberação de serviço que se destina a ser compatível com versões anteriores.
  • Faça alterar o AssemblyVersion para uma liberação que você sabe que está quebrando as alterações.

Basta dar uma olhada nos atributos da versão no 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")]

Tenha em atenção que é a AssemblyFileVersion que contém todas as informações de assistência interessantes (é a parte de revisão desta versão que indica qual é o Service Pack), enquanto a AssemblyVersion é corrigida num 2.0.0.0 antigo e chato. Qualquer alteração no AssemblyVersion forçaria todas as aplicações .NET referenciando o mscorlib.dll a recompilar contra a nova versão!

570
Daniel Fortunov

AssemblyVersion praticamente permanece interno ao .NET, enquanto AssemblyFileVersion é o que o Windows vê. Se você for para as propriedades de um Assembly em um diretório e mudar para a guia version, o AssemblyFileVersion é o que você verá no topo. Se você classificar arquivos por versão, isso é o que é usado pelo Explorer.

O AssemblyInformationalVersion mapeia para a "Versão do Produto" e destina-se a ser puramente "humano-usado".

AssemblyVersion é certamente o mais importante, mas eu também não pularia AssemblyFileVersion. Se você não fornecer AssemblyInformationalVersion, o compilador o adicionará, retirando a parte de "revisão" do seu número de versão e deixando o major.minor.build.

42
Bob King

AssemblyInformationalVersion e AssemblyFileVersion são exibidos quando você exibe as informações de "Versão" em um arquivo através do Windows Explorer, exibindo as propriedades do arquivo. Esses atributos, na verdade, são compilados em um recurso VERSION_INFO que é criado pelo compilador.

AssemblyInformationalVersion é o valor "Versão do produto". AssemblyFileVersion é o valor "Versão do arquivo".

O AssemblyVersion é específico para os assemblies .NET e é usado pelo carregador .NET Assembly para saber qual versão de um Assembly carregar/vincular em tempo de execução.

Destes, o único que é absolutamente exigido pelo .NET é o atributo AssemblyVersion. Infelizmente, ele também pode causar o maior número de problemas quando muda indiscriminadamente, especialmente se você for forte ao nomear seus conjuntos.

21
Scott Dorman

Para manter esta questão atualizada, vale a pena ressaltar que AssemblyInformationalVersion é usado pelo NuGet e reflete a versão do pacote incluindo qualquer sufixo de pré-lançamento.

Por exemplo, um AssemblyVersion de 1.0.3. * Empacotado com o asp.net core dotnet-cli

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

Produz um pacote com a versão 1.0.3-ci-7 que você pode inspecionar com reflexão usando:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);
8
KCD

Vale a pena notar algumas outras coisas:

1) Como mostrado na caixa de diálogo Propriedades do Windows Explorer para o arquivo de montagem gerado, existem dois locais chamados "Versão do arquivo". Aquele visto no cabeçalho da caixa de diálogo mostra o AssemblyVersion, não o AssemblyFileVersion.

Na seção Outras informações de versão, há outro elemento chamado "Versão do arquivo". É aqui que você pode ver o que foi inserido como o AssemblyFileVersion.

2) AssemblyFileVersion é apenas texto simples. Ele não precisa estar em conformidade com as restrições do esquema de numeração que o AssemblyVersion faz (<build> <65K, por exemplo). Pode ser 3.2. <Release tag text>. <Datetime>, se desejar. Seu sistema de compilação terá que preencher os tokens.

Além disso, não está sujeito à substituição de curinga que o AssemblyVersion é. Se você apenas tiver um valor de "3.0.1. *" No AssemblyInfo.cs, é exatamente o que será mostrado no elemento Outras informações da versão-> Versão do arquivo.

3) Eu não sei o impacto sobre um instalador de usar algo diferente de números de versão de arquivo numérico, no entanto.

7
DavidM

Quando AssemblyVersion de um assembly é alterado, se ele tiver nome forte, os assemblies de referência precisam ser recompilados, caso contrário, o assembly não carrega! Se não tiver nome forte, se não for explicitamente adicionado ao arquivo de projeto, ele não será copiado para o diretório de saída quando for construído, portanto, você pode perder montagens dependentes, especialmente após limpar o diretório de saída.

2
linquize