DekGenius.com
[ Team LiB ] Previous Section Next Section

Recipe 11.25 Comparing Version Information of Two Executable Modules

Problem

You need to programmatically compare the version information of two executable modules. An executable module is a file that contains executable code such as an EXE or DLL file. The ability to compare the version information of two executable modules can be very useful to an application if it is trying to determine if it has all of the "right" pieces present to execute or when deciding on an assembly to dynamically load through reflection. This trick is also useful when an application is looking for the newest version of a file or DLL from many files or DLLs spread out in the local filesystem or on a network.

Solution

Use the CompareFileVersions method to compare executable module version information. This method accepts two filenames, including their paths, as parameters. The version information of each module is retrieved and compared. This file returns a FileComparison enumeration, defined as follows:

public enum FileComparison
{
    Error = 0,
    File1IsNewer = 1,
    File2IsNewer = 2,
    FilesAreSame = 3
}

The code for the CompareFileVersions method is:

public FileComparison CompareFileVersions(string file1, string file2)
{
    FileComparison retValue = FileComparison.Error;
    // do both files exist?
    if (!File.Exists(file1))
    {
        Console.WriteLine(file1 + " does not exist");
    }
    else if (!File.Exists(file2))
    {
        Console.WriteLine(file2 + " does not exist");
    }
    else
    {
        // get the version information
        FileVersionInfo file1Version = FileVersionInfo.GetVersionInfo(file1);
        FileVersionInfo file2Version = FileVersionInfo.GetVersionInfo(file2);

        // check major
        if (file1Version.FileMajorPart > file2Version.FileMajorPart)
        {
            Console.WriteLine(file1 + " is a newer version");
            retValue = FileComparison.File1IsNewer;
        }
        else if (file1Version.FileMajorPart < file2Version.FileMajorPart)
        {
            Console.WriteLine(file2 + " is a newer version");
            retValue = FileComparison.File2IsNewer;
        }
        else // major version is equal, check next...
        {
            // check minor
            if (file1Version.FileMinorPart > file2Version.FileMinorPart)
            {
                Console.WriteLine(file1 + " is a newer version");
                retValue = FileComparison.File1IsNewer;
            }
            else if (file1Version.FileMinorPart < file2Version.FileMinorPart)
            {
                Console.WriteLine(file2 + " is a newer version");
                retValue = FileComparison.File2IsNewer;
            }
            else // minor version is equal, check next...
            {
                // check build
                if (file1Version.FileBuildPart > file2Version.FileBuildPart)
                {
                    Console.WriteLine(file1 + " is a newer version");
                    retValue = FileComparison.File1IsNewer;
                }
                else if (file1Version.FileBuildPart < file2Version.FileBuildPart)
                {
                    Console.WriteLine(file2 + " is a newer version");
                    retValue = FileComparison.File2IsNewer;
                }
                else // build version is equal, check next...
                {
                    // check private
                    if (file1Version.FilePrivatePart > file2Version.FilePrivatePart)
                    {
                        Console.WriteLine(file1 + " is a newer version");
                        retValue = FileComparison.File1IsNewer;
                    }
                    else if (file1Version.FilePrivatePart < 
                              file2Version.FilePrivatePart)
                    {
                        Console.WriteLine(file2 + " is a newer version");
                        retValue = FileComparison.File2IsNewer;
                    }
                    else
                    {
                        // identical versions.
                        Console.WriteLine("The files have the same version");
                        retValue = FileComparison.FilesAreSame;
                    }
                }
            }
        }
    }
    return retValue;
}

Discussion

Not all executable modules have version information. If you load a module with no version information using the FileVersionInfo class, you will not throw an exception, nor will you get null back for the object reference. Instead, you will get a valid FileVersionInfo object with all data members in their initial state (which is null for .NET objects).

Assemblies actually have two sets of version information: the version information available in the assembly manifest and the PE (Portable Executable) file version information. FileVersionInfo reads the assembly manifest version information.

The first action this method takes is to determine whether the two files passed in to the file1 and file2 parameters actually exist. If so, the static GetVersionInfo method is called on the FileVersionInfo class with each file passed in as a parameter.

The CompareFileVersions method attempts to compare each portion of the file's version number using the following properties of the FileVersionInfo object returned by GetVersionInfo:


FileMajorPart

The first 2 bytes of the version number.


FileMinorPart

The second 2 bytes of the version number.


FileBuildPart

The third 2 bytes of the version number.


FilePrivatePart

The final 2 bytes of the version number.

The full version number is comprised of these four parts, making up an 8-byte number representing the file's version number.

The CompareFileVersions method first compares the FileMajorPart version information of the two files. If these are equal, the FileMinorPart version information of the two files is compared. This continues through the FileBuildPart and finally the FilePrivatePart version information values. If all four parts are equal, the files are considered to have the same version number. If a file is found to have a higher number than the other file, that first file is considered to be of an earlier version than the one with the higher number.

See Also

See the "FileVersionInfo Class" topic in the MSDN documentation.

    [ Team LiB ] Previous Section Next Section