29

How to programmatically check GAC for an assembly?

casperOne
  • 73,706
  • 19
  • 184
  • 253
Jessy
  • 291
  • 1
  • 3
  • 3

5 Answers5

25

Without even trying to get complicated, you could just shell out to gacutil and capture the output. For example, gacutil /l Microsoft.Practices.Unity gives me:

Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31
bf3856ad364e35, processorArchitecture=MSIL

Number of items = 1

versus gacutil /l Some.Nonexistant.Assembly:

Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:

Number of items = 0

This is easy to implement and parse and isn't dependent on any third-party implementations.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 2
    Shelling out `gacutil.exe` and capturing the output is my definition of overly complicated, I like to keep things as simple as possible :) If it's between using gacutil and the Fusion API then it might be debatable. See my answer here: http://stackoverflow.com/a/19459379/1004119. – Scott Lerch Oct 18 '13 at 21:41
  • You can't count on gacutil being available in all environments--it's a Visual Studio tool, and not available with a "normal" .NET runtime installation. https://learn.microsoft.com/en-us/dotnet/framework/tools/gacutil-exe-gac-tool – Josh Apr 23 '18 at 14:05
  • You can't distribute gacutil.exe . It's against the license. – joe Aug 19 '20 at 07:41
9

It's better to use ReflectionOnlyLoad Method. this method loads an assembly into the reflection-only context, where it can be examined but not executed.

casperOne
  • 73,706
  • 19
  • 184
  • 253
BALKANGraph
  • 2,031
  • 1
  • 15
  • 16
6

From .NET, the reflection API - Assembly.Load(...) will throw a FileNotFoundException if it does not find the assembly. The API requires a fully qualified assembly name, so I assume it must be in the GAC. I am using it to test for the presence of SQL Server Compact Edition:

Assembly foo = Assembly.Load("System.Data.SqlServerCe, Version=3.5.1.0, " +
    "Culture=neutral, PublicKeyToken=89845dcd8080cc91");
casperOne
  • 73,706
  • 19
  • 184
  • 253
StrayPointer
  • 1,304
  • 14
  • 16
  • 1
    Assembly.Load searches other locations as well: The default load context contains assemblies found by probing the global assembly cache, the host assembly store if the runtime is hosted (for example, in SQL Server), and the ApplicationBase and PrivateBinPath of the application domain. - http://msdn.microsoft.com/cs-cz/library/dd153782.aspx – Bohdan Oct 08 '11 at 18:01
  • 1
    It is maybe an idea to combine this with the http://msdn.microsoft.com/en-us/library/system.reflection.assembly.globalassemblycache(v=vs.110).aspx GlobalAssemblyCache property – ErikEJ Feb 21 '14 at 12:10
2

You can use the Fusion COM API. Junfeng Zhang wrote a managed wrapper. It's from 2004, though, so I don't know how well it works anymore.

David Brown
  • 35,411
  • 11
  • 83
  • 132
  • 2
    Using the COM-based Fusion API is the true proper way, but attempting an Assembly.Load and catching the FileNotFoundException is much easier. – Mike Post Feb 20 '10 at 22:33
  • @Mike Post: But it also has the unfortunate side-effect of loading the assembly into the app domain, which is not really what is desired here. Ease-of-use does not always trump correctness (I'd argue that it rarely does). – casperOne May 30 '11 at 15:22
  • 1
    ReflectionOnlyLoad has the same side effect of loading the assembly into the app domain. Read the fine print in the docs. It's just a different work around for having to use the complicated unmanaged COM Fusion API. – Mike Post Jun 01 '11 at 21:30
  • Manager wrapper moved to GitHub https://github.com/kekyo/GACWrap – Bohumil Janda Nov 18 '21 at 06:53
0

Do you want to probe the GAC for an assembly or do you just want to know that the assembly exists on the machine?

If you dont care that the assembly is actually in the GAC, but just loadable on the machine (from the appdomain) you can just use LoadAssembly with the assemblies name (strong, common, full, etc). If the assembly can be loaded by Fusion it will be and then you will know it exists.

GrayWizardx
  • 19,561
  • 2
  • 30
  • 43