14

I'm looking the way to read all assemblies (.dlls) used by my app.

In a standard C# project there is "References" folder, when it is expanded I can read all libraries used.

My goal is programatically read all assemblies which are used by each project in my solution.

Finally I'd like to see what libraries are used by my compiled *.exe application.

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Maciej
  • 10,423
  • 17
  • 64
  • 97

6 Answers6

14

Have you looked at Assembly.GetReferencedAssemblies?

Note that any references you don't use won't end up being emitted into the metadata, so you won't see them at execution time.

I've used GetReferencedAssemblies recursively before now to find a named type without having to specify the assembly.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
11

To do this properly, you need to walk the assemblies, picking up the dependencies... if your exe needs Dll_A, and Dll_A needs Dll_B (even if the exe doesn't reference it), then your exe also needs Dll_B.

You can query this (on any assembly) via reflection; it takes a little work (especially to guard against circular references, which do happen; here's an example that starts at the "entry assembly", but this could just as easily be any assembly:

    List<string> refs = new List<string>();
    Queue<AssemblyName> pending = new Queue<AssemblyName>();
    pending.Enqueue(Assembly.GetEntryAssembly().GetName());
    while(pending.Count > 0)
    {
        AssemblyName an = pending.Dequeue();
        string s = an.ToString();
        if(refs.Contains(s)) continue; // done already
        refs.Add(s);
        try
        {
            Assembly asm = Assembly.Load(an);
            if(asm != null)
            {
                foreach(AssemblyName sub in asm.GetReferencedAssemblies())
                {
                    pending.Enqueue(sub);
                }
                foreach (Type type in asm.GetTypes())
                {
                    foreach (MethodInfo method in type.GetMethods(
                        BindingFlags.Static | BindingFlags.Public |
                             BindingFlags.NonPublic))
                    {
                        DllImportAttribute attrib = (DllImportAttribute)
                            Attribute.GetCustomAttribute(method,
                                typeof(DllImportAttribute));
                        if (attrib != null && !refs.Contains(attrib.Value))
                        {
                            refs.Add(attrib.Value);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex.Message);
        }
    }
    refs.Sort();
    foreach (string name in refs)
    {
        Console.WriteLine(name);
    }
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Will this also detect unmanaged dll's that are used via PInvoke, or does it only pick up manages dll's? – Matt Warren Aug 20 '09 at 14:10
  • Managed dlls only. You could use reflection to look for the P/Invoke methods - but it would be slightly different reflection. – Marc Gravell Aug 20 '09 at 14:18
  • How would I do that? My knowledge of reflection is limited, can you point me in the right direction? – Matt Warren Aug 20 '09 at 14:48
  • Could you perhaps update this using an extension method on `Assembly` with `yield` and returning an `IEnumerable` or `IEnumerable`? – julealgon Apr 16 '14 at 21:48
  • @julealgon any particular reason? I mean: if somebody wants that, they can just ... do that locally? – Marc Gravell Apr 16 '14 at 21:56
  • To people thinking it's not possible to have circular references, have a look at [this SO question](http://stackoverflow.com/q/1316518/1364007) or [this MSDN blog](http://blogs.msdn.com/b/kirillosenkov/archive/2013/11/23/circular-assembly-references-in-the-net-framework.aspx) for some examples. – Wai Ha Lee Jan 14 '16 at 13:58
2
System.Reflection.Assembly []ar=AppDomain.CurrentDomain.GetAssemblies();

foreach (System.Reflection.Assembly a in ar)
{
 Console.WriteLine("{0}", a.FullName);
}
KV Prajapati
  • 93,659
  • 19
  • 148
  • 186
  • See this comment why it's not the best solution: https://stackoverflow.com/questions/1305005/how-to-get-names-of-dlls-used-by-application#comment1136536_1305023 – Grzegorz Smulko Jul 01 '19 at 13:48
0

You can use AppDomain.GetAssemblies.
But this will give ALL assemblies used explicitly or implicitly in your application.

Dmytrii Nagirniak
  • 23,696
  • 13
  • 75
  • 130
  • 3
    As I understand it, that will give the ones which have already been loaded. There may be ones which are referenced in the metadata, but haven't been loaded yet as they haven't been needed in the execution so far. – Jon Skeet Aug 20 '09 at 09:32
  • Thanks for your tip! This AppDomain.CurrentDomain.GetAssemblies () was also interesting – Maciej Aug 20 '09 at 09:52
0

If you have an Assembly object, you can call GetReferencedAssemblies() on it to get any references that assembly uses. To get a list of assemblies the currently running project uses, you can use:

System.Reflection.Assembly.GetExecutingAssembly().GetReferencedAssemblies()
Matthew Scharley
  • 127,823
  • 52
  • 194
  • 222
0

I guess you can use:

AssemblyName[] assemblies = this.GetType().Assembly.GetReferencedAssemblies();
Fossmo
  • 2,862
  • 4
  • 25
  • 47