查找二进制文件的版本

最后发布: 2011-05-13 19:12:47


问题

有谁知道我如何找到已传递给函数的二进制文件的版本?

我从此页面获得以下代码:

def version(fpath):
    f = open(fpath, 'rb')

    s = f.read(1024)
    print s

    f.close()

但是,这并没有给我任何类似于上述网站显示的有用输出。

编辑 :@BoazYaniv告诉我,文件格式在此问题中起着重要的作用。 这是Windows EXE档案

python version binaryfiles
回答

您有一个用于解析EXE文件的现成模块: http : //code.google.com/p/pefile/

您可以使用以下代码阅读它:

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']

如您所见,Windows EXE(和DLL)文件存储两种不同的版本,即FileVersion和ProductVersion。 很多时候它们是相同的,但有时它们可​​能有所不同-这完全取决于制作EXE的人。

编辑:

为了使事情更复杂,PE字符串表中的这两个字符串并不是Windows编译器可以保存版本的唯一位置。 EXE中存储了两个附加的FileVersion和ProductVersion值,只有它们以32位整数对的形式存储,每个值又被分解为两个16位整数(Windows API中的WORD表示)。 总而言之,每个版本值(FileVersion和ProductVersion)都有4个16位WORD,它们表示版本的点分隔部分。 您也可以使用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

可是等等! 这还不是全部:您至少还有一个地方可以查找版本:在另一个名为OPTIONAL_HEADER的结构中,您可以找到另外两个名为MajorImageVersion和MinorImageVersion的值。 它们代表了整个版本的前两个部分,因此,一个文件的ProductVersion或FileVersion为6.1.7600.150,通常其MajorImageVersion为6,而MinorImageVersion为1。您可以使用pe.OPTIONAL_HEADER.MajorImageVersion获得它们pe.OPTIONAL_HEADER.MajorImageVersionpe.OPTIONAL_HEADER.MinorImageVersion

所有这些值(如果我没记错的话,有5个不同的值)通常都是等效的(如果忽略字符串表中的自由格式字符串值有时具有的值),但是看到FileVersions和ProductVersions并不相同是很常见的,并且您还应该准备其他惊喜。


回答

我们使用此代码从一个可执行文件中提取版本,以供其他程序使用。

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.

---包含评论---

这要求安装Windows绑定的Python。 它们在这里可用: http : //starship.python.net/~skippy/win32/ 这也将这种解决方案限制在Windows平台上(这可能是最终项目中的重要因素,也可能不是)。