How to read assembly attributes

In my program, how can I read the properties set in AssemblyInfo.cs:

[assembly: AssemblyTitle("My Product")]
[assembly: AssemblyDescription("...")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Radeldudel inc.")]
[assembly: AssemblyProduct("My Product")]
[assembly: AssemblyCopyright("Copyright @ me 2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

I'd like to display some of these values to the user of my program, so I'd like to know how to load them from the main program and from komponent assemblies I'm using.


Solution 1:

This is reasonably easy. You have to use reflection. You need an instance of Assembly that represents the assembly with the attributes you want to read. An easy way of getting this is to do:

typeof(MyTypeInAssembly).Assembly

Then you can do this, for example:

object[] attributes = assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);

AssemblyProductAttribute attribute = null;
if (attributes.Length > 0)
{
   attribute = attributes[0] as AssemblyProductAttribute;
}

Referencing attribute.Product will now give you the value you passed to the attribute in your AssemblyInfo.cs. Of course, if the attribute you look for can occur more than once, you may get multiple instances in the array returned by GetCustomAttributes, but this is not usually an issue for assembly level attributes like the ones you hope to retrieve.

Solution 2:

I've created this extension method that uses Linq:

public static T GetAssemblyAttribute<T>(this System.Reflection.Assembly ass) where T :  Attribute
{
    object[] attributes = ass.GetCustomAttributes(typeof(T), false);
    if (attributes == null || attributes.Length == 0)
        return null;
    return attributes.OfType<T>().SingleOrDefault();
}

and then you can conveniently use it like that:

var attr = targetAssembly.GetAssemblyAttribute<AssemblyDescriptionAttribute>();
if(attr != null)
     Console.WriteLine("{0} Assembly Description:{1}", Environment.NewLine, attr.Description);

Solution 3:

Ok, perhaps a bit out of date now for the original question but I will present this for future reference anyway.

If you want to do it from inside the assembly itself then use the following :

using System.Runtime.InteropServices;
using System.Reflection;

object[] customAttributes = this.GetType().Assembly.GetCustomAttributes(false);

You can then iterate through all of the custom attributes to find the one(s) you require e.g.

foreach (object attribute in customAttributes)
{
  string assemblyGuid = string.Empty;    

  if (attribute.GetType() == typeof(GuidAttribute))
  {
    assemblyGuid = ((GuidAttribute) attribute).Value;
    break;
  }
}

Solution 4:

Okay, I'm tried to go through many resources to find a method to extract .dll attributes for a Assembly.LoadFrom(path) . But unfortunately I couldn't find any good resource. And this question was the top most result for searching on c# get assembly attributes (For me at least) So I thought of sharing my work.

I wrote following simple Console Program to retrieve general assembly attributes after many hours of struggle. Here I have provided the code so anyone can use it for further reference work.

I use CustomAttributes property for this. Feel free to comment on this approach

Code :

using System;
using System.Reflection;

namespace MetaGetter
{
    class Program
    {
        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom("Path to assembly");

            foreach (CustomAttributeData attributedata in assembly.CustomAttributes)
            {
                Console.WriteLine(" Name : {0}",attributedata.AttributeType.Name);

                foreach (CustomAttributeTypedArgument argumentset in attributedata.ConstructorArguments)
                {
                    Console.WriteLine("   >> Value : {0} \n" ,argumentset.Value);
                }
            }

            Console.ReadKey();
        }
    }
}

Sample Output :

Name : AssemblyTitleAttribute
   >> Value : "My Product"

Solution 5:

I personally really like the implementation of lance Larsen and his static AssemblyInfo class.

One basically pastes the class in his assembly (I usually use the already existing AssemblyInfo.cs file as it fits naming convention)

The code to paste is:

internal static class AssemblyInfo
{
    public static string Company { get { return GetExecutingAssemblyAttribute<AssemblyCompanyAttribute>(a => a.Company); } }
    public static string Product { get { return GetExecutingAssemblyAttribute<AssemblyProductAttribute>(a => a.Product); } }
    public static string Copyright { get { return GetExecutingAssemblyAttribute<AssemblyCopyrightAttribute>(a => a.Copyright); } }
    public static string Trademark { get { return GetExecutingAssemblyAttribute<AssemblyTrademarkAttribute>(a => a.Trademark); } }
    public static string Title { get { return GetExecutingAssemblyAttribute<AssemblyTitleAttribute>(a => a.Title); } }
    public static string Description { get { return GetExecutingAssemblyAttribute<AssemblyDescriptionAttribute>(a => a.Description); } }
    public static string Configuration { get { return GetExecutingAssemblyAttribute<AssemblyConfigurationAttribute>(a => a.Configuration); } }
    public static string FileVersion { get { return GetExecutingAssemblyAttribute<AssemblyFileVersionAttribute>(a => a.Version); } }

    public static Version Version { get { return Assembly.GetExecutingAssembly().GetName().Version; } }
    public static string VersionFull { get { return Version.ToString(); } }
    public static string VersionMajor { get { return Version.Major.ToString(); } }
    public static string VersionMinor { get { return Version.Minor.ToString(); } }
    public static string VersionBuild { get { return Version.Build.ToString(); } }
    public static string VersionRevision { get { return Version.Revision.ToString(); } }

    private static string GetExecutingAssemblyAttribute<T>(Func<T, string> value) where T : Attribute
    {
        T attribute = (T)Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(T));
        return value.Invoke(attribute);
    }
}

You add a using System; to the top of the file and you're good to go.

For my applications i use this class to set/get/work with my local users settings using:

internal class ApplicationData
{

    DirectoryInfo roamingDataFolder;
    DirectoryInfo localDataFolder;
    DirectoryInfo appDataFolder;

    public ApplicationData()
    {
        appDataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AssemblyInfo.Product,"Data"));
        roamingDataFolder = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),AssemblyInfo.Product));
        localDataFolder   = new DirectoryInfo(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), AssemblyInfo.Product));

        if (!roamingDataFolder.Exists)            
            roamingDataFolder.Create();

        if (!localDataFolder.Exists)
            localDataFolder.Create();
        if (!appDataFolder.Exists)
            appDataFolder.Create();

    }

    /// <summary>
    /// Gets the roaming application folder location.
    /// </summary>
    /// <value>The roaming data directory.</value>
    public DirectoryInfo RoamingDataFolder => roamingDataFolder;


    /// <summary>
    /// Gets the local application folder location.
    /// </summary>
    /// <value>The local data directory.</value>
    public DirectoryInfo LocalDataFolder => localDataFolder;

    /// <summary>
    /// Gets the local data folder location.
    /// </summary>
    /// <value>The local data directory.</value>
    public DirectoryInfo AppDataFolder => appDataFolder;
}

Have a look at Larsens website (MVP), he has cool stuff to draw Inspiration from.