Найти версию двоичного файла - PullRequest
1 голос
/ 13 мая 2011

Кто-нибудь знает, как я могу найти версию двоичного файла, который был передан моей функции?

Я получил следующий код с этой страницы :

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

    s = f.read(1024)
    print s

    f.close()

Однако это не дает мне никакого полезного вывода, подобного тому, что показывает упомянутый веб-сайт.

Редактировать : @BoazYaniv говорит мне, что формат файла играет важную роль в этомпроблема.Это EXE-файл Windows

Ответы [ 2 ]

7 голосов
/ 13 мая 2011

У вас есть готовый модуль для разбора 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.

Edit:

Просто чтобы сделать вещи более сложными, эти две строки в таблице строк PE - не единственное место, где компиляторы Windows могут сохранить версию. В EXE хранятся два дополнительных значения FileVersion и ProductVersion, только они хранятся в виде пар 32-разрядных целых чисел, каждое из которых, в свою очередь, разбивается на два 16-разрядных целых числа (говорят WORD в Windows API). В целом, каждое значение версии (FileVersion и ProductVersion) имеет 4 16-битных слова, которые представляют разделенные точками части версии. Вы также можете получить их, используя 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.MinorImageVersion.

Все эти значения (5 различных, если я их правильно считаю) обычно эквивалентны (если игнорировать дополнительное строковое значение произвольной формы, которое иногда имеют значения в таблице строк), но довольно часто можно увидеть FileVersions и ProductVersions, которые не то же самое, и вы также должны быть готовы к другим сюрпризам.

4 голосов
/ 13 мая 2011

Мы используем этот код для извлечения версий из одного из наших исполняемых файлов для использования в других программах.

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 (которые могут или не могут быть важным фактором в конечном проекте).

...