Due to multiple environments (BizTalk) I have to manage and also oversee deployments over these environments I have created a tool to compare the GACs (Global Assembly Cache) of machines. The first tool I created was a simple command line one and was quite limited (and a bit flawed oops). Then recently we started using 64bit machines and I realized the old utility does not work so good anymore. Thus I created a new utility (Win form based) that take inconsideration things like 32bit/64bit as well.
First some background on how this utility works:
This tool only list the difference between the GACs of the machines. No changes are made - That would be a very interesting and perhaps hairy experience!
To get the information of what is installed in the GAC is really simple. As long as you have local admin rights on the machine you can do a plain old command line 'dir' command on \\machine\c$\windows\assembly and its sub directories. There are multiple sub directories like GAC, GAC_MSIL etc.
1. Under each of these there are sub directories that list the assembly names (not the assembly itself)
2. Under these there is another sub directory that reports the version, culture and public token key values (name of directory)
3. Under these the actual dlls are stored.
Then it is simply a matter to list the directories and processing the names and put them into a list. Once you have the lists you can compare them to each other and get the differences.
Just one interesting bit. The plain GAC directory was the default for .Net 1.x. The GAC_MSIL is the default for .Net 2.0. There are also GAC_32 and GAC_64 ones that contain 32bit and 64bit assemblies - of course GAC_64 only applies to 64bit machines.
I'm not listing the entire source code here but here is the main function that does the bulk of the work.
private void GetGACFiles(string rootDirectory)
{
if (Directory.Exists(rootDirectory))
{
string[] assemblyDirectories = Directory.GetDirectories(rootDirectory);
foreach (string assemblyDirectory in assemblyDirectories)
{
string[] versionTokenDirectories = Directory.GetDirectories(assemblyDirectory);
foreach (string versionTokenDirectory in versionTokenDirectories)
{
string[] assemblyFiles = Directory.GetFiles(versionTokenDirectory, "*.dll"); //There should only be one... Don't loose your head
foreach (string assemblyFile in assemblyFiles) //sometimes there are multiple files
{
if (gacEntry.AssemblyPath.ToLower().Contains(gacEntry.AssemblyName.ToLower() + ".dll"))
{
GACEntry gacEntry = new GACEntry();
gacEntry.AssemblyName = Path.GetFileName(assemblyDirectory);
gacEntry.AssemblyPath = assemblyFile;
gacEntry.AssemblyVersion = GetVersionFromVersionToken(versionTokenDirectory);
gacEntry.Culture = GetCultureFromVersionToken(versionTokenDirectory);
gacEntry.PublicKeyToken = GetTokenFromVersionToken(versionTokenDirectory);
if (!assemblies.Contains(gacEntry)) //avoid duplicates
assemblies.Add(gacEntry);
}
}
}
}
}
}
There you have it. Not rocket science. It is provided as is...