Determine if assembly is installed in the GAC

C

Cramer

I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc in
the GAC.

I have googled this and failed to find anything useful.

Thanks
 
W

Willy Denoyette [MVP]

Cramer said:
I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc in
the GAC.

I have googled this and failed to find anything useful.

Thanks

You'll have to cal into the fusion API's (native code API's and COM).
Here is a completes sample that illustrates how one can retrieve the path of
an assembly in the GAC.

// Note that this requires V2 of the framework!!!!.
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace GacStuff
{
internal class GacApi
{
[DllImport("fusion.dll")]
internal static extern IntPtr CreateAssemblyCache(
out IAssemblyCache ppAsmCache,
int reserved);

}
// GAC Interfaces - IAssemblyCache. As a sample, non used vtable entries
declared as dummy.
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
internal interface IAssemblyCache
{
int Dummy1();
[PreserveSig()]
IntPtr QueryAssemblyInfo(
int flags,
[MarshalAs(UnmanagedType.LPWStr)]
String assemblyName,
ref ASSEMBLY_INFO assemblyInfo);
int Dummy2();
int Dummy3();
int Dummy4();
}
[StructLayout(LayoutKind.Sequential)]
internal struct ASSEMBLY_INFO
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public String currentAssemblyPath;
public int cchBuf;
}

class Program
{
static void Main()
{
try
{
Console.WriteLine(QueryAssemblyInfo("System"));
}
catch(System.IO.FileNotFoundException e)
{
Console.WriteLine(e.Message);
}
}
// If assemblyName is not fully qualified, a random matching may be
returned!!!!
public static String QueryAssemblyInfo(String assemblyName)
{
ASSEMBLY_INFO assembyInfo = new ASSEMBLY_INFO ();
assembyInfo.cchBuf = 512;
assembyInfo.currentAssemblyPath = new String('\0',
assembyInfo.cchBuf) ;
IAssemblyCache assemblyCache = null;
// Get IAssemblyCache pointer
IntPtr hr = GacApi.CreateAssemblyCache(out assemblyCache, 0);
if (hr == IntPtr.Zero)
{
hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref
assembyInfo);
if(hr != IntPtr.Zero)
Marshal.ThrowExceptionForHR(hr.ToInt32());
}
else
Marshal.ThrowExceptionForHR(hr.ToInt32());
return assembyInfo.currentAssemblyPath;
}
}
}

Willy.
 
C

Cramer

Thanks for the code! I never would have had the time to come up with this
and instead documented assumptions my code would have instead have made
about the existance of the assembly in the GAC. Now it will be able to test
and report on those assumptions when invalid, before choking. I'll give it a
whirl.

-Cramer


Willy Denoyette said:
Cramer said:
I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc
in the GAC.

I have googled this and failed to find anything useful.

Thanks

You'll have to cal into the fusion API's (native code API's and COM).
Here is a completes sample that illustrates how one can retrieve the path
of an assembly in the GAC.

// Note that this requires V2 of the framework!!!!.
using System;
using System.Runtime.InteropServices;
using System.Text;

namespace GacStuff
{
internal class GacApi
{
[DllImport("fusion.dll")]
internal static extern IntPtr CreateAssemblyCache(
out IAssemblyCache ppAsmCache,
int reserved);

}
// GAC Interfaces - IAssemblyCache. As a sample, non used vtable
entries declared as dummy.
[ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
internal interface IAssemblyCache
{
int Dummy1();
[PreserveSig()]
IntPtr QueryAssemblyInfo(
int flags,
[MarshalAs(UnmanagedType.LPWStr)]
String assemblyName,
ref ASSEMBLY_INFO assemblyInfo);
int Dummy2();
int Dummy3();
int Dummy4();
}
[StructLayout(LayoutKind.Sequential)]
internal struct ASSEMBLY_INFO
{
public int cbAssemblyInfo;
public int assemblyFlags;
public long assemblySizeInKB;
[MarshalAs(UnmanagedType.LPWStr)]
public String currentAssemblyPath;
public int cchBuf;
}

class Program
{
static void Main()
{
try
{
Console.WriteLine(QueryAssemblyInfo("System"));
}
catch(System.IO.FileNotFoundException e)
{
Console.WriteLine(e.Message);
}
}
// If assemblyName is not fully qualified, a random matching may be
returned!!!!
public static String QueryAssemblyInfo(String assemblyName)
{
ASSEMBLY_INFO assembyInfo = new ASSEMBLY_INFO ();
assembyInfo.cchBuf = 512;
assembyInfo.currentAssemblyPath = new String('\0',
assembyInfo.cchBuf) ;
IAssemblyCache assemblyCache = null;
// Get IAssemblyCache pointer
IntPtr hr = GacApi.CreateAssemblyCache(out assemblyCache, 0);
if (hr == IntPtr.Zero)
{
hr = assemblyCache.QueryAssemblyInfo(1, assemblyName, ref
assembyInfo);
if(hr != IntPtr.Zero)
Marshal.ThrowExceptionForHR(hr.ToInt32());
}
else
Marshal.ThrowExceptionForHR(hr.ToInt32());
return assembyInfo.currentAssemblyPath;
}
}
}

Willy.
 
I

Ignacio Machin ( .NET/ C# MVP )

I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc in
the GAC.

I have googled this and failed to find anything useful.

Thanks

Hi,

IT should be simple, first you need a reference to the assembly (you
can use Assembly.GetAssembly(typeof( XXXX ) ); where XXXX is defined
in that assembly)
Then using Assembly.Location should be enough.
 
W

Willy Denoyette [MVP]

message
I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc in
the GAC.

I have googled this and failed to find anything useful.

Thanks

Hi,

IT should be simple, first you need a reference to the assembly (you
can use Assembly.GetAssembly(typeof( XXXX ) ); where XXXX is defined
in that assembly)
Then using Assembly.Location should be enough.


But this won't return the GAC location, nor will it tell you whether the
assembly is actually stored in the GAC.

Willy.
 
C

Cramer

RE:
IT should be simple, first you need a reference to the assembly (you
can use Assembly.GetAssembly(typeof( XXXX ) ); where XXXX is defined
in that assembly)
Then using Assembly.Location should be enough.


I should have been more specific. I want to know if an assembly is
installed in the GAC *before* attempting to load it. This would be akin to
using File.Exists() before attempting to open a file.

Your approach assumes that the assembly is already loaded, which it is not
in my case. In my case I want to determine if an assembly of a particular
version etc is in the GAC, then load it if it's there, or write the fact to
a log if it's not in the GAC.

-Cramer
 
P

parez

I'm wondering if there is an easy way to programmatically determine if an
assembly is installed in the GAC.

This would be similar to our ability to easily determine if a file exists
(File.Exists(path)) - but for an assembly, of a particular version, etc in
the GAC.

I have googled this and failed to find anything useful.

Thanks

Try Assembly.LoadWithPartialName("SomeName");

if returned value is null then it is not in gac..
if you get a non null value , then check the GlobalAssemblyCache.

that mite work..
 
P

parez

RE:


I should have been more specific. I want to know if an assembly is
installed in the GAC *before* attempting to load it. This would be akin to
using File.Exists() before attempting to open a file.

Your approach assumes that the assembly is already loaded, which it is not
in my case. In my case I want to determine if an assembly of a particular
version etc is in the GAC, then load it if it's there, or write the fact to
a log if it's not in the GAC.

-Cramer

Try Assembly.LoadWithPartialName("SomeName");

if returned value is null then it is not in gac..
if you get a non null value , then check the GlobalAssemblyCache.

that mite work..
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top