Які відмінності між AssemblyVersion, AssemblyFileVersion та AssemblyInformationalVersion?


860

Є три атрибути збірної версії. Які відмінності? Чи нормально, якщо я використовую AssemblyVersionі ігнорую решту?


MSDN каже:

  • Складання зборів :

    Визначає версію збірки, що присвоюється.

  • СкладанняFileVersion :

    Доручає компілятору використовувати певний номер версії для ресурсу версії файлу Win32. Версія файлу Win32 не повинна бути такою ж, як номер версії збірки.

  • ЗбіркаІнформаційна версія :

    Визначає додаткову інформацію про версію для маніфесту збірки.


Це подальший досвід щодо того, які найкращі практики використання атрибутів збірки?

Відповіді:


907

ЗбіркаВерсія

Де будуть виглядати інші збірки, на які посилається ваша збірка. Якщо ця кількість змінюється, інші збори повинні оновити свої посилання на вашу збірку! Оновіть цю версію лише в тому випадку, якщо вона порушує зворотну сумісність. AssemblyVersionПотрібно.

Я використовую формат: major.minor . Це призведе до:

[assembly: AssemblyVersion("1.0")]

Якщо ви суворо стежите за SemVer, це означає, що ви оновлюєте лише тоді, коли зміниться основні , так що 1.0, 2.0, 3.0 тощо.

СкладанняFileVersion

Використовується для розгортання. Ви можете збільшити цю кількість для кожного розгортання. Він використовується програмами налаштування. Використовуйте його для позначення збірок, які мають однакові AssemblyVersion, але створені з різних збірок.

У Windows його можна переглянути у властивостях файлу.

ЗборкаFileVersion не є обов'язковою. Якщо не вказано, використовується AssemblyVersion.

Я використовую формат: major.minor.patch.build , де я слідую за SemVer за першими трьома частинами та використовую номер збирання buildserver для останньої частини (0 для локальної збірки). Це призведе до:

[assembly: AssemblyFileVersion("1.3.2.254")]

Будьте в курсі, що System.Version називає ці частини як major.minor.build.revision!

ЗбіркаІнформаційнаВерсія

Версія продукту складання. Це версія, яку ви використовуєте під час розмови з клієнтами або для показу на вашому веб-сайті. Ця версія може бути рядок, як-от " 1.0 Release Candidate ".

Це AssemblyInformationalVersionнеобов'язково. Якщо не вказано, використовується AssemblyFileVersion.

Я використовую формат: major.minor [.patch] [редакція як рядок] . Це призведе до:

[assembly: AssemblyInformationalVersion("1.0 RC1")]

4
Для AssemblyFileVersion, "Якщо можливо, нехай він генерується MSBuild" - Чому? Ви просто продовжили пояснювати вагомий привід, щоб вручну контролювати це :)
мо.

3
Попередження про формат AssemblyInformationalVersion все ще існує у VS2010 сьогодні (21 травня 2013 р.), І ваше посилання недійсне.
reinierpost

22
На жаль, клас Class Version визначає, major.minor[.build[.revision]]і не major.minor.revision.buildтак у даній відповіді номери збирання та ревізії будуть замінені, якби ви використовували властивості класу або System.Reflection.Assembly.GetExecutingAssembly().GetName().Versionвиявляли номери збірки та ревізії.
thinkOfaNumber

9
@thinkOfaNumber Ваше право щодо класу версій, але це спосіб версії Microsoft. Мені особисто здається, що дивним є відсутність збірної кількості в кінці, і тому я лише ставлю свій формат як приклад, заснований на Semantic Versioning . Ви можете безкоштовно використовувати спосіб Microsoft або власний шлях.
Ремі ван Дуйкерен

6
Слід зазначити, що для AssemblyInformationalVersion, якщо пропущено, AssemblyFileVersionвикористовується. Тоді AssemblyVersion якщо обидва опущені.
Дражен Беловук

588

Версія версій збірок у .NET може бути заплутаною перспективою, враховуючи, що в даний час існує щонайменше три способи визначення версії для вашої збірки.

Ось три основні атрибути збірки, пов’язані з версією:

// 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")]

За угодою, чотири частини версії називаються як Major Version , Minor Version , Будувати і Revision .

AssemblyFileVersionПризначений для однозначної ідентифікації збірки з індивідуальної збірки

Зазвичай ви вручну встановлюєте Major and Minor AssemblyFileVersion для відображення версії збірки, а потім збільшуєте збірку та / або перегляд кожного разу, коли ваша система збирання збирає збірку. AssemblyFileVersion повинен дозволяти вам однозначно ідентифікувати збірку збірки, щоб ви могли використовувати її як вихідну точку для налагодження будь-яких проблем.

У моєму поточному проекті ми маємо сервер збірки, що кодує номер списку змін з нашого сховища керування джерелами у частинах зборки та редагування AssemblyFileVersion. Це дозволяє нам відображати безпосередньо зі збірки до його вихідного коду для будь-якої збірки, створеної сервером збірки (без необхідності використання міток або гілок у керуванні джерелом або вручну зберігати будь-які записи випущених версій).

Цей номер версії зберігається у ресурсі версії Win32 і його можна побачити під час перегляду сторінок властивостей Windows Explorer для складання.

CLR не переймається і не вивчає AssemblyFileVersion.

Це AssemblyInformationalVersionпризначено для представлення версії всього вашого продукту

AssemblyInformationalVersion призначений для того, щоб дозволити послідовну версію всього продукту, яка може складатися з безлічі збірок, які незалежно розроблені, можливо, з різними політиками версій і потенційно розроблені різними командами.

«Наприклад, версія 2.0 продукту може містити кілька збірок; одна з цих збірок позначена як версія 1.0, оскільки це нова збірка, яка не постачається у версії 1.0 того ж продукту. Зазвичай ви встановлюєте основні та другорядні частини цього номера версії, щоб представити загальнодоступну версію вашого продукту. Потім ви збільшуєте деталі для складання та ревізії кожного разу, коли ви пакуєте повний продукт із усіма його збірками ». - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 57

CLR не переймається і не вивчає Асамблейську інформаційну версію.

AssemblyVersionЄ єдиною версією , що CLR піклується про (але піклується про все AssemblyVersion)

CLR використовується AssemblyVersion для прив'язки до сильно названих збірок. Він зберігається у таблиці метаданих маніфесту AssemblyDef вбудованої збірки та в таблиці AssemblyRef будь-якої збірки, на яку посилається.

Це дуже важливо, оскільки це означає, що коли ви посилаєтесь на чітко названу збірку, ви щільно прив'язані до конкретної AssemblyVersion цієї збірки. Весь AssemblyVersion повинен відповідати точності, щоб обов'язковість пройшла успішно. Наприклад, якщо ви посилаєтесь на версію 1.0.0.0 сильно названої збірки під час збирання, але лише версія 1.0.0.1 цієї збірки доступна під час виконання, прив'язка не вдасться! (Тоді вам доведеться обійти це, використовуючи перенаправлення прив'язки .)

Плутанина щодо того, чи AssemblyVersionмає збігатися весь . (Так.)

Існує невелика плутанина навколо того, чи повинен цілий AssemblyVersion точно відповідати, щоб збірка була завантажена. Деякі люди знаходять помилкове переконання, що лише основна та менша частини Асамблеї Версії повинні відповідати, щоб обов'язковість пройшла успішно. Це розумне припущення, однак воно в кінцевому підсумку невірно (як .NET 3.5), і перевірити це для вашої версії CLR тривіально. Просто виконайте цей зразок коду .

На моїй машині навантаження на другу збірку виходить з ладу, і в останніх двох рядках журналу плавлення чітко видно, чому:

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

Я думаю, що джерело цієї плутанини, мабуть, пов'язане з тим, що Microsoft спочатку мав бути трохи поблажливішим до цього суворого відповідності повної версії AssemblyVersion, співставляючи лише основні та малі версії:

"Під час завантаження збірки CLR автоматично знайде останню встановлену версію обслуговування, що відповідає основній / другорядній версії запитуваної збірки." - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 56

Така поведінка в Beta 1 1.0 CLR, однак ця функція була видалена до випуску 1.0, і не вдалося повторно вийти на поверхню в .NET 2.0:

"Примітка. Я щойно описав, як ви повинні думати номери версій. На жаль, CLR не розглядає номери версій таким чином. [In .NET 2.0], CLR розглядає номер версії як непрозоре значення, і якщо збірка залежить від версії 1.2.3.4 іншої збірки, CLR намагається завантажити лише версію 1.2.3.4 (якщо не має місце переадресація прив'язки ). Однак Microsoft планує змінити завантажувач CLR у майбутній версії, щоб він завантажував останню збірку / версію для даної основної / другорядної версії збірки. Наприклад, у майбутній версії CLR, якщо завантажувач намагається знайти версію 1.2.3.4 збірки, а версія 1.2.5.0 існує, завантажувач автоматично підбирає останню версію обслуговування. Це буде дуже вітальною зміною завантажувача CLR - я за те, що не можу чекати ». - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 164 (акцент міна)

Оскільки ця зміна досі не була здійснена, я вважаю, що з впевненістю можна припустити, що компанія Microsoft відслідковувала цей намір, і зараз, можливо, пізно змінити це. Я спробував пошукати в Інтернеті, щоб дізнатися, що сталося з цими планами, але я не зміг знайти відповіді. Я все-таки хотів дійти до цього.

Тож я надіслав електронною поштою Джеффу Ріхтеру і запитав його прямо - я зрозумів, що хтось знає, що сталося, це буде він.

Він відповів не менше ніж на 12 годин у суботу вранці, і уточнив, що завантажувач .NET 1.0 Beta 1 реалізував цей механізм "автоматичного відкоту" для підбору останньої доступної збірки та перегляду збірки, але така поведінка була повернено раніше. NET 1.0 поставляється. Пізніше планувалося відродити це, але він не встиг перед тим, як з'явиться CLR 2.0. Потім з'явився Silverlight, який став пріоритетним для команди CLR, тому ця функціональність ще більше затрималася. Тим часом більшість людей, які були в часи CLR 1.0 Beta 1, з тих пір перейшли, тому навряд чи це побачить світло дня, незважаючи на всю наполегливу роботу, яка вже була вкладена в нього.

Нинішня поведінка, здається, тут залишається.

Варто також відзначити з мого обговорення з Jeff, що AssemblyFileVersion було додано лише після видалення механізму "автоматичного прокрутки", тому що після 1.0 Beta 1 будь-яка зміна AssemblyVersion була переломною зміною для ваших клієнтів. ніде безпечно зберігати номер складання. AssemblyFileVersion - це безпечний притулок, оскільки він ніколи не перевіряється автоматично CLR. Можливо, це зрозуміліше, маючи два окремі номери версій, з окремими значеннями, а не намагатися зробити це розмежування між майором / мінором (розривом) та складанням / переглядом (нерозривних) частин асамблеї Версії.

Підсумок: ретельно подумайте, коли ви зміните свій AssemblyVersion

Мораль полягає в тому, що якщо ви відправляєте збірки, на які збираються посилатися інші розробники, вам потрібно бути дуже обережним щодо того, коли ви (і не робите) змінити AssemblyVersion цих збірок. Будь-які зміни в AssemblyVersion означатимуть, що розробникам додатків доведеться або перекомпілювати проти нової версії (для оновлення цих записів AssemblyRef), або використовувати переадресації збірки прив'язки, щоб вручну змінити прив'язку.

  • Не змінюйте AssemblyVersion на сервісний випуск, який повинен бути сумісним назад.
  • Як змінити AssemblyVersion для випуску , що ви знаєте , мають відмінності.

Просто погляньте ще на атрибути версії на 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")]

Зауважте, що саме AssemblyFileVersion містить всю цікаву інформацію про обслуговування (саме частина Revision цієї версії розповідає про те, який пакет оновлень ви працюєте), тим часом AssemblyVersion встановлюється на нудному старому 2.0.0.0. Будь-яка зміна AssemblyVersion змусить усі програми .NET, що посилаються на mscorlib.dll, перекомпілювати з нової версії!


9
Чудова відповідь. Я думаю, що найважливіший пункт, який ви зробили - і що MS слід чітко рекомендувати, - це вносити зміни до AssemblyVersion тоді і лише тоді, коли нова версія порушує зворотну сумісність.
mwolfe02

1
Одне із запитань, яке я неодноразово задаю собі, - коли я повинен змінити кожний із цих номерів версій, ваші пункти на “AssemblyVersion” додали цьому чіткості, і вся відповідь була цікавою прочитаною.
RyanfaeScotland

Я бачу багато відповідей, які пояснюють поняття, що стоять за цими трьома речами. Але як вони відносяться до редагованих номерів версій у властивостях проекту? Коли ви натискаєте Інформація про збірку ..., ви отримуєте можливість змінити дві версії. І там, коли зміна Version Assembly змінює папку, в якій знайдено user.config, а зміна File Version змінює номер версії, показану при натисканні правою кнопкою миші на файл exe та перехід до його властивостей. Тож як ці два номери версій відповідають AssemblyVersion, AssemblyFileVersion та AssemblyInformationalVersion?
Кайл Делані

Посилання на публікацію в блозі, яку ви спочатку писали, дає номер 404. Чи є для цього нове місце?
Роб К

@RobK: Ах, вибачте. Цей веб-сайт не працює, але весь вміст публікації в блозі відтворений у відповіді, тому ви нічого не пропускаєте. Я зараз видалю недіюче посилання.
Даніель Фортунов

43

AssemblyVersionзначною мірою залишається внутрішнім у .NET, тоді AssemblyFileVersionяк Windows бачить. Якщо ви перейдете до властивостей збірки, що сидить у каталозі та переходить на вкладку версії, AssemblyFileVersionце те, що ви побачите вгорі. Якщо ви сортуєте файли за версією, саме це використовує Провідник.

AssemblyInformationalVersionКарти в «Версії продукту» і призначається , щоб бути чисто «людиною використовуваним».

AssemblyVersionце, звичайно, найважливіше, але я також не пропустив би AssemblyFileVersion. Якщо ви не надаєте AssemblyInformationalVersion, компілятор додає його для вас, знімаючи "перегляд" частини вашого номера версії та залишаючи major.minor.build.


23

AssemblyInformationalVersionі AssemblyFileVersionвідображаються при перегляді інформації "Версія" у файлі через Провідник Windows шляхом перегляду властивостей файлу. Ці атрибути фактично збираються в VERSION_INFOресурс, який створюється компілятором.

AssemblyInformationalVersionє «версія продукту» значення. AssemblyFileVersionє значенням "Версія файлу".

AssemblyVersionДещо специфічною є для .NET збірок і використовується .NET збірки завантажувача , щоб дізнатися , яка версія збірки для завантаження / зв'язування під час виконання.

З них єдиний, який абсолютно вимагає .NET - це AssemblyVersionатрибут. На жаль, він також може викликати найбільші проблеми, коли він змінюється без розбору, особливо якщо ви сильно називаєте свої збори.


9

Щоб зберегти актуальність цього питання, варто підкреслити, що AssemblyInformationalVersionвикористовується NuGet і відображає версію пакета, включаючи будь-який суфікс попереднього випуску.

Наприклад, AssemblyVersion 1.0.3. *, Упакований з ядром dotnet-cli asp.net

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

Випускає пакет з версією 1.0.3-ci-7, який ви можете оглянути з відображенням, використовуючи:

CustomAttributeExtensions.GetCustomAttribute<AssemblyInformationalVersionAttribute>(asm);

7

Варто відзначити деякі інші речі:

1) Як показано в діалоговому вікні "Властивості провідника" для згенерованого файлу складання, у двох місцях називається "Версія файлу". Той, який бачите у заголовку діалогового вікна, показує AssemblyVersion, а не AssemblyFileVersion.

У розділі Інформація про іншу версію є ще один елемент, який називається "Версія файлу". Тут ви можете побачити, що було введено як AssemblyFileVersion.

2) AssemblyFileVersion - це просто звичайний текст. Він не повинен відповідати обмеженням схеми нумерації, які робить AssemblyVersion (<build> <65K, наприклад). Це може бути 3.2. <Текст тегу випуску>. <Час часу>, якщо ви хочете. Ваша система збирання доведеться заповнити лексем.

Більше того, заміною підстановкою символів, що є AssemblyVersion, вона не підлягає. Якщо ви просто маєте значення "3.0.1. *" У AssemblyInfo.cs, саме це відображатиметься в Іншій інформації про версію-> Файл Версія файлу.

3) Я не знаю, як впливає на інсталятора використання чогось іншого, ніж числові номери версій файлів.


2

Коли зміна AssemblyVersion збірки змінюється, якщо вона має сильну назву, референтні збори потрібно перекомпілювати, інакше збірка не завантажується! Якщо воно не має сильного імені, якщо його явно не додано до файлу проекту, воно не буде скопійовано у вихідний каталог під час збирання, щоб ви могли пропустити залежні збірки, особливо після очищення вихідного каталогу.


Це дуже цікаво! Не могли б ви детальніше розробити частину "не буде скопійовано у вихідний каталог"? Можливо, посилання на те, де визначена така поведінка. Я ніколи не розумів, чому деякі непрямі залежності іноді копіюються, але не завжди. Це має бути на 100% пов’язане з цим.
julealgon
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.