Determining the Versions of an Assembly That Are Registered in the Global Assembly Cache (GAC)






Determining the Versions of an Assembly That Are Registered in the Global Assembly Cache (GAC)

Problem

You need to determine all of the versions of an assembly that are currently installed in the GAC.

Solution

Use the PrintGACRegisteredVersions method (implemented here) to display all of the versions (both native and managed) of an assembly in the GAC. In order to be complete, the code looks for .dll, .exe, and the native versions of .dll and .exe files in the Global Assembly Cache.

	public static void PrintGACRegisteredVersions(string assmFileName)
	{

	    Console.WriteLine("Searching for GAC Entries for {0}\r\n", assmFileName);
	    // Get the filename without the extension as that is the subdirectory
	    // name in the GAC where it would be registered.
	    string assmFileNameNoExt = Path.GetFileNameWithoutExtension(assmFileName);

	    // Need to look for both the native images as well as "regular" .dlls and .exes.
	    string searchDLL = assmFileNameNoExt + ".dll";
	    string searchEXE = assmFileNameNoExt + ".exe";
	    string searchNIDLL = assmFileNameNoExt + ".ni.dll";
	    string searchNIEXE = assmFileNameNoExt + ".ni.exe";

The Directory.GetFiles method is used to determine if any of those versions are present in the GAC, which is located in the [Windows]\ASSEMBLY folder.

The ASSEMBLY folder is not visible through Windows Explorer, as the GAC shell extension gets in the way. But if you run a Command Prompt window, you can maneuver to the [Windows]\ASSEMBLY folder and see how things are stored in the GAC.


Finally, all of the files are combined into a master ArrayList using the AddRange method:

	// Get the path to the GAC using GetWinDir from 20.7.
	string gacPath = GetWinDir( ) + @"\ASSEMBLY\";

	// Go get all of the possible file derivatives in the GAC.
	string [] dllFiles = Directory.GetFiles(gacPath, searchDLL,
	                        SearchOption.AllDirectories);
	string [] exeFiles = Directory.GetFiles(gacPath, searchEXE,
	                        SearchOption.AllDirectories);
	string [] niDllFiles = Directory.GetFiles(gacPath, searchNIDLL,
	                        SearchOption.AllDirectories);
	string [] niExeFiles = Directory.GetFiles(gacPath, searchNIEXE,
	                        SearchOption.AllDirectories);

	ArrayList files = new ArrayList(5);
	files.AddRange(dllFiles);
	files.AddRange(exeFiles);
	files.AddRange(niDllFiles);
	files.AddRange(niExeFiles);

Now that you have a master list of the versions of this file in the GAC, you display the information for each individual item by examining the FileVersionInfo and writing it out to the console:

	    foreach (string file in files)
	{
	        // Grab the version info and print.
	        FileVersionInfo fileVersion = FileVersionInfo.GetVersionInfo(file);
	        if (file.IndexOf("NativeImage") != -1)
	        {
	            Console.WriteLine("Found {0} in the GAC under {1} as a native image",
	                assmFileNameNoExt, Path.GetDirectoryName(file));
	        }
	        else
	        {
	            Console.WriteLine("Found {0} in the GAC under {1} with version " +
	                    "information:\r\n{2}",
	                            assmFileNameNoExt, Path.GetDirectoryName(file),
	                    fileVersion.ToString( ));
	        }
	    }
	}

The output from this when looking for mscorlib looks like this:

	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages1_v1.1.4322\mscorlib\
	1.0.5000.0_ _b77a5c561934e089_a4b3b51f as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages1_v1.1.4322\mscorlib\
	1.0.5000.0_ _b77a5c561934e089_605b23c2 as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages1_v1.0.3705\MSCORLIB\
	1.0.3300.0_ _b77a5c561934e089_22016492 as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\GAC_32\mscorlib\2.0.0.0_ _
	b77a5c561934e089 with version information:
	File:             C:\WINDOWS\ASSEMBLY\GAC_32\mscorlib\2.0.0.0_ _b77a5c561934e089\
	mscorlib.dll
	InternalName:     mscorlib.dll
	OriginalFilename: mscorlib.dll
	FileVersion:      2.0.50712.6 (lab23df.050712-0600)
	FileDescription:  Microsoft Common Language Runtime Class Library
	Product:          Microsoftr .NET Framework
	ProductVersion:   2.0.50712.6
	Debug:            False
	Patched:          False
	PreRelease:       False
	PrivateBuild:     False
	SpecialBuild:     False
	Language:         English (United States)

	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.50712_32\
	mscorlib\043d0388db36f94390f023725a82a5e4 as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.50601_32\
	mscorlib\e56acc8ebce07f4db51f6f98c84419c2 as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.50215_32\
	mscorlib\5259bd1f47da3e329e6706b9d018132f as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.50110_32\
	mscorlib\1958e0d8502fff3f9b6b032a1e517867 as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.50110_32\
	mscorlib\07185e97384cd23eb6c91147f5db32ce as a native image
	Found mscorlib in the GAC under C:\WINDOWS\ASSEMBLY\NativeImages_v2.0.41115_32\
	mscorlib\ce295c2bd5b3d53cbcdca987ec346d99 as a native image

Discussion

The ability to have multiple versions of assemblies on a machine and having absolute binding mechanisms to the specific version of an assembly, were proclaimed as the cure to .dll hell .dll hell was the case in which two applications linked to a .dll of the same name in a common folder (like System32), but each application needed a different version of the .dll. Problems occurred when you attempted to run one or the other application, depending upon which version was present. With assemblies and the GAC, this scenario occurs only when the application is improperly configured by allowing it to use newer versions of an assembly automatically or via publisher policy issues. Perhaps things are better now. In any case, they are different, and the starting point for debugging assembly loads is to figure out what is on the system. This can be helped by looking at the Assembly Binding Log Viewer (FUSLOGVW.exe). But having a way to just see what is on the system with a particular filename and what versions are included can be a very useful thing.

See Also

See the "Directory Class," "ArrayList Class," and "FileVersionInfo Class" topics in the MSDN documentation.



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows