Другое

Получить версию файла сборки в .NET

Узнайте, как получить версию файла сборки в .NET с помощью рефлексии и FileVersionInfo. Полное руководство с примерами кода для .NET Framework и .NET Core.

Как получить версию файла сборки в .NET?

В .NET в AssemblyInfo существуют два разных номера версии:

  1. AssemblyVersion – указывает версию самой сборки, к которой применяется атрибут.
  2. AssemblyFileVersion – сообщает компилятору использовать конкретный номер версии для ресурса версии Win32. Номер версии Win32 не обязан совпадать с номером версии сборки.

Версию сборки можно получить так:

csharp
Version version = Assembly.GetEntryAssembly().GetName().Version;

Но как программно получить AssemblyFileVersion в C#?

В .NET вы можете получить версию файла сборки программно, используя атрибут AssemblyFileVersionAttribute через рефлексию. Самый прямой способ — воспользоваться методом GetCustomAttribute<T>(), чтобы получить AssemblyFileVersionAttribute и прочитать его свойство Version.


Содержание


Использование метода GetCustomAttribute

Основной способ получения версии файла сборки — доступ к AssemblyFileVersionAttribute через рефлексию. Вот как это реализовать:

csharp
using System.Reflection;

public static string GetAssemblyFileVersion()
{
    var assembly = Assembly.GetEntryAssembly();
    if (assembly == null) return null;
    
    var attribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
    return attribute?.Version;
}

Этот подход напрямую читает атрибут AssemblyFileVersionAttribute, который указан в вашем файле AssemblyInfo.cs. Согласно документации Microsoft, атрибут AssemblyFileVersionAttribute конкретно указывает компилятору использовать определённый номер версии для ресурса версии Win32 файла.

Альтернативный подход с FileVersionInfo

Если метод GetCustomAttribute возвращает null (что может произойти в некоторых сценариях), вы можете откатиться к чтению информации о версии файла непосредственно из файла сборки:

csharp
using System.Diagnostics;
using System.Reflection;

public static string GetAssemblyFileVersion()
{
    try
    {
        var assembly = Assembly.GetEntryAssembly();
        if (assembly == null) return null;
        
        var attribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
        if (attribute != null)
        {
            return attribute.Version;
        }
        
        // Откат к чтению из файла
        var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
        return fileVersionInfo.FileVersion;
    }
    catch
    {
        return null;
    }
}

Этот двойной подход гарантирует, что вы получите версию файла даже тогда, когда метод на основе атрибута не сработает, как показано в примерах из CSharpCodi.


Обработка разных .NET Framework

Существует важное различие между .NET Framework и .NET Core/.NET 5+:

.NET Framework

csharp
// Работает в .NET Framework
var assembly = Assembly.GetEntryAssembly();
var attribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
return attribute?.Version;

.NET Core и .NET 5+

csharp
// Работает в .NET Core и .NET 5+
using System.Runtime.InteropServices;

public static string GetAssemblyFileVersion()
{
    var assembly = Assembly.GetExecutingAssembly();
    var assemblyName = assembly.GetName();
    var assemblyVersion = assemblyName.Version.ToString();
    
    try
    {
        // Попытка получить атрибут версии файла
        var attribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
        if (attribute != null)
        {
            return attribute.Version;
        }
    }
    catch
    {
        // Откат к версии сборки, если атрибут версии файла недоступен
    }
    
    return assemblyVersion;
}

Полные примеры реализации

Ниже приведена комплексная реализация, которая обрабатывает различные сценарии:

csharp
using System;
using System.Diagnostics;
using System.Reflection;

public static class AssemblyVersionHelper
{
    /// <summary>
    /// Получает версию файла сборки (AssemblyFileVersion)
    /// </summary>
    /// <returns>Строка версии файла или null, если недоступна</returns>
    public static string GetAssemblyFileVersion()
    {
        try
        {
            var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
            
            // Попытка получить атрибут AssemblyFileVersion
            var fileVersionAttribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
            if (fileVersionAttribute != null)
            {
                return fileVersionAttribute.Version;
            }
            
            // Откат к чтению из файла
            var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
            if (!string.IsNullOrEmpty(fileVersionInfo.FileVersion))
            {
                return fileVersionInfo.FileVersion;
            }
            
            // Финальный откат к версии сборки
            var assemblyName = assembly.GetName();
            return assemblyName.Version?.ToString();
        }
        catch
        {
            return null;
        }
    }

    /// <summary>
    /// Получает версию сборки (AssemblyVersion)
    /// </summary>
    /// <returns>Строка версии сборки или null, если недоступна</returns>
    public static string GetAssemblyVersion()
    {
        try
        {
            var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
            var assemblyName = assembly.GetName();
            return assemblyName.Version?.ToString();
        }
        catch
        {
            return null;
        }
    }

    /// <summary>
    /// Получает информационную версию (AssemblyInformationalVersion)
    /// </summary>
    /// <returns>Строка информационной версии или null, если недоступна</returns>
    public static string GetInformationalVersion()
    {
        try
        {
            var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
            var informationalVersionAttribute = assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>();
            return informationalVersionAttribute?.InformationalVersion;
        }
        catch
        {
            return null;
        }
    }
}

Сравнение с AssemblyVersion

Ниже таблица сравнения различных типов версий:

Тип версии Атрибут Назначение Метод получения
Версия сборки AssemblyVersion Версия самой сборки Assembly.GetName().Version
Версия файла AssemblyFileVersion Ресурс версии Win32 файла GetCustomAttribute<AssemblyFileVersionAttribute>().Version
Информационная версия AssemblyInformationalVersion Дополнительная информация о версии GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion

Как объясняется в документации Microsoft, AssemblyFileVersion предназначен именно для ресурса версии Win32 файла и не обязан совпадать с номером версии сборки.


Лучшие практики и обработка ошибок

При работе с информацией о версии сборки учтите следующие рекомендации:

  1. Обрабатывайте нулевые ссылки: всегда проверяйте null при использовании GetCustomAttribute.
  2. Предоставляйте механизмы отката: используйте несколько способов получения информации о версии.
  3. Учитывайте контекст: используйте GetEntryAssembly() для основной сборки приложения.
  4. Обработка ошибок: оборачивайте получение версии в блоки try-catch для надёжности.

Ниже пример улучшенной версии с более надёжной обработкой ошибок:

csharp
public static string SafeGetAssemblyFileVersion()
{
    try
    {
        var assembly = Assembly.GetEntryAssembly() 
                      ?? Assembly.GetExecutingAssembly()
                      ?? Assembly.GetCallingAssembly();
        
        if (assembly == null) return "Unknown";
        
        // Попытка нескольких подходов
        var fileVersionAttribute = assembly.GetCustomAttribute<AssemblyFileVersionAttribute>();
        if (fileVersionAttribute != null)
        {
            return fileVersionAttribute.Version;
        }
        
        var fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
        if (!string.IsNullOrEmpty(fileVersionInfo.FileVersion))
        {
            return fileVersionInfo.FileVersion;
        }
        
        var assemblyName = assembly.GetName();
        return assemblyName.Version?.ToString() ?? "Unknown";
    }
    catch (Exception ex)
    {
        // Логируйте исключение, если у вас есть инфраструктура логирования
        return "Unknown";
    }
}

Эта всесторонняя стратегия гарантирует надёжное получение версии файла сборки во всех .NET‑платформах и сценариях, как показано в различных примерах из Stack Overflow и других авторитетных источников.


Заключение

Чтобы получить версию файла сборки программно в .NET:

  1. Основной метод: assembly.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version
  2. Альтернативный метод: FileVersionInfo.GetVersionInfo(assembly.Location).FileVersion как резерв
  3. Кроссплатформенность: учитывайте различия между .NET Framework и .NET Core
  4. Обработка ошибок: реализуйте проверки null и блоки try-catch
  5. Лучшие практики: создайте вспомогательный класс с несколькими методами получения версии

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


Источники

  1. Stack Overflow – Как получить версию файла сборки
  2. Microsoft Learn – Использование AssemblyVersion и AssemblyFileVersion
  3. Edi Wang – Получить версию приложения в .NET Core
  4. CSharpCodi – Примеры Assembly.GetCustomAttribute
  5. Microsoft Learn – Метод Attribute.GetCustomAttribute
  6. Daily .NET Tips – Программно получить версию сборки
Авторы
Проверено модерацией
Модерация