I know how to load an assembly from a filename, and also from the GAC. As My .msi file will put a dll project into the GAC, I'm wondering if it's possible to load it from the GAC unknowing the FullName (I mean just with the assembly name, or even the dll filename), because I have to Load this assembly from another project.
Asked
Active
Viewed 6,403 times
2 Answers
22
Here is a piece of code that allows to do this, and an exemple:
string path = GetAssemblyPath("System.DirectoryServices");
Assembly.LoadFrom(path);
Note if you need a specific processor architecture, since it supports partial name, you can write this kind of things:
// load from the 32-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=X86");
// load from the 64-bit GAC
string path = GetAssemblyPath("Microsoft.Transactions.Bridge.Dtc, ProcessorArchitecture=AMD64");
This is the implementation:
/// <summary>
/// Gets an assembly path from the GAC given a partial name.
/// </summary>
/// <param name="name">An assembly partial name. May not be null.</param>
/// <returns>
/// The assembly path if found; otherwise null;
/// </returns>
public static string GetAssemblyPath(string name)
{
if (name == null)
throw new ArgumentNullException("name");
string finalName = name;
AssemblyInfo aInfo = new AssemblyInfo();
aInfo.cchBuf = 1024; // should be fine...
aInfo.currentAssemblyPath = new String('\0', aInfo.cchBuf);
IAssemblyCache ac;
int hr = CreateAssemblyCache(out ac, 0);
if (hr >= 0)
{
hr = ac.QueryAssemblyInfo(0, finalName, ref aInfo);
if (hr < 0)
return null;
}
return aInfo.currentAssemblyPath;
}
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
private interface IAssemblyCache
{
void Reserved0();
[PreserveSig]
int QueryAssemblyInfo(int flags, [MarshalAs(UnmanagedType.LPWStr)] string assemblyName, ref AssemblyInfo assemblyInfo);
}
[StructLayout(LayoutKind.Sequential)]
private struct AssemblyInfo
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public string currentAssemblyPath;
public int cchBuf; // size of path buf.
}
[DllImport("fusion.dll")]
private static extern int CreateAssemblyCache(out IAssemblyCache ppAsmCache, int reserved);

Simon Mourier
- 132,049
- 21
- 248
- 298
-
Wow !It seems complicated ! I was looking for something more simple, but IMHO the solution you're proposing is certainly the best for achieving this ! Thank you, I'll try it if my need become mandatory some day ! – metalcam May 26 '11 at 13:42
-
Awesome work Simon. I've used this answer for a TypeResolver class as explained on Code Project : http://www.codeproject.com/Articles/641878/Resolving-an-unreferenced-partial-type-name-using – John O Nov 05 '14 at 21:18
-2
Yes, this is the whole point of the GAC. The runtime will look in the GAC first, before even looking in the current directory.

paulmey
- 1,046
- 9
- 3
-
1Thank your for this detail, but I was wondering if there was a trick to do for example `Assembly.Load("myAssembly")` instead of `Assembly.Load("myAssembly, Version=xxxxx, PublicKeyToken=xxxxxx")` IMHO, it's not possible but I'm now looking for knowing the Assembly Name of a Primary Output in my MSI, and putting it into the app.config, in order to dynamically get the Assembly Name in the code. – metalcam May 25 '11 at 09:45