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.
|