开发者

Find Version of Binary File

Does anyone know how I can find the version of a binary file that has been passed to my function?

I got the following code from this page:

开发者_C百科
def version(fpath):
    f = open(fpath, 'rb')

    s = f.read(1024)
    print s

    f.close()

However, this does not give me any useful output similar to what the mentioned website shows.

Edit: @BoazYaniv tells me that the file format plays in important part in this problem. This is a windows EXE file


You have a ready-made module for parsing EXE files: http://code.google.com/p/pefile/

You could read it using the following code:

import pefile

pe = pefile.PE(r'C:\Windows\notepad.exe')
FileVersion    = pe.FileInfo[0].StringTable[0].entries['FileVersion']
ProductVersion = pe.FileInfo[0].StringTable[0].entries['ProductVersion']

As you can see, Windows EXE (and DLL) files store two different kinds of versions, FileVersion and ProductVersion. Many times they are the same, but sometimes they may different - it all depends on the one who made the EXE really.

Edit:

Just to make things more complex, these two strings in the PE string table aren't the only place where Windows compilers may save the version. There are two addiotnal FileVersion and ProductVersion values stored in the EXE, only they are stored as pairs of 32-bit integers, each of them is broken, in turn, into two 16-bit integers (WORDs in Windows API speak). Altogether, each version value (FileVersion and ProductVersion) has 4 16-bit WORDs which represent the dot-separated parts of the version. You can get them too, using pefile:

pe = pefile.PE(r'C:\Windows\notepad.exe')
FileVersionLS    = pe.VS_FIXEDFILEINFO.FileVersionLS
FileVersionMS    = pe.VS_FIXEDFILEINFO.FileVersionMS
ProductVersionLS = pe.VS_FIXEDFILEINFO.ProductVersionLS
ProductVersionMS = pe.VS_FIXEDFILEINFO.ProductVersionMS

FileVersion = (FileVersionMS >> 16, FileVersionMS & 0xFFFF, FileVersionLS >> 16, FileVersionLS & 0xFFFF)
ProductVersion = (ProductVersionMS >> 16, ProductVersionMS & 0xFFFF, ProductVersionLS >> 16, ProductVersionLS & 0xFFFF)

print 'File version:    %s.%s.%s.%s' % FileVersion 
print 'Product version: %s.%s.%s.%s' % ProductVersion

But wait! This is not all: you have at least one more place where you could look to find the version: Inside another structure, called OPTIONAL_HEADER, you can find another two values called MajorImageVersion and MinorImageVersion. They represent the two first parts of the whole version, so a file which has a ProductVersion or FileVersion of, say, 6.1.7600.150, would usually have a MajorImageVersion of 6 and a MinorImageVersion of 1. You could get them with pe.OPTIONAL_HEADER.MajorImageVersion and pe.OPTIONAL_HEADER.MinorImageVersion.

All these values (5 different ones, if I count them right) are usually equivalent (if you ignore the extra freeform string value the ones at a string table sometimes have), but its quite common to see FileVersions and ProductVersions that are not the same, and you should also be ready for other surprises as well.


We use this code to pull versions from one of our executables for use throughout other programs.

import win32api

try:
    info = win32api.GetFileVersionInfo('rpmsrv.exe', "\\")
    ms = info['FileVersionMS']
    ls = info['FileVersionLS']
    __version__ = "%d.%d.%d.%d" % (win32api.HIWORD(ms), win32api.LOWORD (ms),
                                 win32api.HIWORD (ls), win32api.LOWORD (ls))
except:
    __version__ = '5.1.1.000' # some appropriate default here.

--- To encompass the comments ---

This requires that the Windows Bindings for Python be installed. They're available here: http://starship.python.net/~skippy/win32/. This also limits this solution to Windows platforms (which may or may not be an important factor in the final project).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜