This is a recipe for extracting file version information from Windows files, using the Win32 API.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # fileversion.py
import dynwin.windll as windll
import dynwin.oracle as oracle
import calldll
cstring = windll.cstring
version = windll.module('version')
vs_fixed_file_info = oracle.Oracle(
'fixed file info structure',
'Nllhhhhhhhhlllllll',
('signature',
'struc_version',
'file_version_msl',
'file_version_msh',
'file_version_lsl',
'file_version_lsh',
'product_version_msl',
'product_version_msh',
'product_version_lsl',
'product_version_lsh',
'file_flags_mask',
'file_flags',
'file_os',
'file_type',
'file_subtype',
'file_date_ms',
'file_date_ls')
)
def _get_file_version_info_size(filename):
return version.GetFileVersionInfoSize(cstring(filename), 0)
def _get_file_version_info(filename, verinfosize):
buffer = windll.membuf(verinfosize)
result = version.GetFileVersionInfo(cstring(filename),
0,
buffer.size(),
buffer.address())
return result, buffer
def _ver_query_value(buffer):
verbufptr = windll.membuf(32)
verbuflen = windll.membuf(32)
result = version.VerQueryValue(buffer.address(),
cstring('\\'),
verbufptr,
verbuflen)
verbuffer = calldll.read_string(calldll.read_long(verbufptr),
calldll.read_long(verbuflen))
dict, size = vs_fixed_file_info.unpack(verbuffer)
msh = str(dict['file_version_msh'])
msl = str(dict['file_version_msl'])
lsh = str(dict['file_version_lsh'])
lsl = str(dict['file_version_lsl'])
file_version = msh + '.' + msl + '.' + lsh + '.' + lsl
return result, file_version
def get_file_version(filename):
verinfosize = _get_file_version_info_size(filename)
if not verinfosize: return None
result, buffer = _get_file_version_info(filename, verinfosize)
if not result: return None
result, file_version = _ver_query_value(buffer)
if not result: return None
return file_version
if __name__ == '__main__':
import os
for file in os.listdir('c:\\winnt\\system32'):
if not os.path.isdir(file):
file_version = get_file_version(file)
print file, file_version
|
Mark Hammond's otherwise excellent win32 extensions do not include a function for extracting file version information. Sam Rushing's windll, calldll, and npstruct modules (http://www.nightmare.com/~rushing/dynwin/) allow calling functions from any DLL, and provide a way to call the win32 API directly. Unfortunately, windll/calldll/npstruct is not documented very well, and it took me awhile to figure out how to do this. Hopefully, this recipe will help others who need to do the same thing or just provide a little more insight into using Sam's modules.