Атрибут Версия файла Windows Python
В прошлый раз я задавал похожий вопрос, но это было о svn-связанной информации о версиях. Теперь мне интересно, как запросить атрибут окна «Версия файла», например, о. длл. Также я безуспешно обратил внимание на модули wmi и win32file.
7 ответов
Вот функция, которая читает все атрибуты файла как словарь:
import win32api #============================================================================== def getFileProperties(fname): #============================================================================== """ Read all properties of the given file return them as a dictionary. """ propNames = ('Comments', 'InternalName', 'ProductName', 'CompanyName', 'LegalCopyright', 'ProductVersion', 'FileDescription', 'LegalTrademarks', 'PrivateBuild', 'FileVersion', 'OriginalFilename', 'SpecialBuild') props = try: # backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc fixedInfo = win32api.GetFileVersionInfo(fname, '\\') props['FixedFileInfo'] = fixedInfo props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536, fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536, fixedInfo['FileVersionLS'] % 65536) # \VarFileInfo\Translation returns list of available (language, codepage) # pairs that can be used to retreive string info. We are using only the first pair. lang, codepage = win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation')[0] # any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle # two are language/codepage pair returned from above strInfo = <> for propName in propNames: strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName) ## print str_info strInfo[propName] = win32api.GetFileVersionInfo(fname, strInfoPath) props['StringFileInfo'] = strInfo except: pass return props
Лучше добавить попытку / за исключением случаев, когда файл не имеет атрибута номера версии.
from win32api import GetFileVersionInfo, LOWORD, HIWORD def get_version_number (filename): try: info = GetFileVersionInfo (filename, "\\") ms = info['FileVersionMS'] ls = info['FileVersionLS'] return HIWORD (ms), LOWORD (ms), HIWORD (ls), LOWORD (ls) except: return 0,0,0,0 if __name__ == '__main__': import os filename = os.environ["COMSPEC"] print ".".join ([str (i) for i in get_version_number (filename)])
import os,filever myPath="C:\\path\\to\\check" for root, dirs, files in os.walk(myPath): for file in files: file = file.lower() # Convert .EXE to .exe so next line works if (file.count('.exe') or file.count('.dll')): # Check only exe or dll files fullPathToFile=os.path.join(root,file) major,minor,subminor,revision=filever.get_version_number(fullPathToFile) print "Filename: %s \t Version: %s.%s.%s.%s" % (file,major,minor,subminor,revision)
Вот версия, которая также работает в средах, отличных от Windows, с использованием pefile-модуля:
import pefile def LOWORD(dword): return dword & 0x0000ffff def HIWORD(dword): return dword >> 16 def get_product_version(path): pe = pefile.PE(path) #print PE.dump_info() ms = pe.VS_FIXEDFILEINFO.ProductVersionMS ls = pe.VS_FIXEDFILEINFO.ProductVersionLS return (HIWORD (ms), LOWORD (ms), HIWORD (ls), LOWORD (ls)) if __name__ == "__main__": import sys try: print "%d.%d.%d.%d" % get_product_version(sys.argv[1]) except: print "Version info not available. Maybe the file is not a Windows executable"
from win32com.client import Dispatch ver_parser = Dispatch('Scripting.FileSystemObject') info = ver_parser.GetFileVersion(path) if info == 'No Version Information Available': info = None
Я обнаружил, что единственный кросс-платформенный ответ (используя pefile ) не смог найти искомую строку версии, которая показана на вкладке «Подробности» окна «Свойства просмотра» файла.DLL в Windows. Однако этот код, основанный на dump_info() функционировать в pefile , может найти те атрибуты, которые включают исходное имя файла, авторские права, название компании, а также версии файлов и продуктов.
Возможно, вам потребуется заменить encoding с другой кодировкой, если они не кодируются с использованием UTF-8.
import pefile PATH_TO_FILE = 'C:\. ' pe = pefile.PE(PATH_TO_FILE) if hasattr(pe, 'VS_VERSIONINFO'): for idx in range(len(pe.VS_VERSIONINFO)): if hasattr(pe, 'FileInfo') and len(pe.FileInfo) > idx: for entry in pe.FileInfo[idx]: if hasattr(entry, 'StringTable'): for st_entry in entry.StringTable: for str_entry in sorted(list(st_entry.entries.items())): print(': '.format( str_entry[0].decode('utf-8', 'backslashreplace'), str_entry[1].decode('utf-8', 'backslashreplace')))
Я нашел это решение на сайте «timgolden». Работает отлично.
from win32api import GetFileVersionInfo, LOWORD, HIWORD def get_version_number (filename): info = GetFileVersionInfo (filename, "\\") ms = info['FileVersionMS'] ls = info['FileVersionLS'] return HIWORD (ms), LOWORD (ms), HIWORD (ls), LOWORD (ls) if __name__ == '__main__': import os filename = os.environ["COMSPEC"] print ".".join ([str (i) for i in get_version_number (filename)])
Вот рабочая версия ответа болота выше, только с использованием стандартной библиотеки. Используйте это как get_version_string(file, «FileVersion») ,
from ctypes import * # returns the requested version information from the given file # # `language` should be an 8-character string combining both the language and # codepage (such as "040904b0"); if None, the first language in the translation # table is used instead # def get_version_string(filename, what, language=None): # VerQueryValue() returns an array of that for VarFileInfo\Translation # class LANGANDCODEPAGE(Structure): _fields_ = [ ("wLanguage", c_uint16), ("padding_", c_uint16), ("wCodePage", c_uint16)] wstr_file = wstring_at(filename) # getting the size in bytes of the file version info buffer size = windll.version.GetFileVersionInfoSizeW(wstr_file, None) if size == 0: raise WinError() buffer = create_string_buffer(size) # getting the file version info data if windll.version.GetFileVersionInfoW(wstr_file, None, size, buffer) == 0: raise WinError() # VerQueryValue() wants a pointer to a void* and DWORD; used both for # getting the default language (if necessary) and getting the actual data # below value = c_void_p(0) value_size = c_uint(0) if language is None: # file version information can contain much more than the version # number (copyright, application name, etc.) and these are all # translatable # # the following arbitrarily gets the first language and codepage from # the list ret = windll.version.VerQueryValueW( buffer, wstring_at(r"\VarFileInfo\Translation"), byref(value), byref(value_size)) if ret == 0: raise WinError() # value points to a byte inside buffer, value_size is the size in bytes # of that particular section # casting the void* to a LANGANDCODEPAGE* lcp = cast(value, POINTER(LANGANDCODEPAGE)) # formatting language and codepage to something like "040904b0" language = "".format( lcp.contents.wLanguage, lcp.contents.wCodePage) # getting the actual data res = windll.version.VerQueryValueW( buffer, wstring_at("\\StringFileInfo\\" + language + "\\" + what), byref(value), byref(value_size)) if res == 0: raise WinError() # value points to a string of value_size characters return wstring_at(value.value, value_size.value)
Вот версия, которая не требует никаких дополнительных библиотек. Я не мог использовать win32api, как все предлагали:
Копируется только в случае, если оригинал пропал без вести.
import array from ctypes import * def get_file_info(filename, info): """ Extract information from a file. """ # Get size needed for buffer (0 if no info) size = windll.version.GetFileVersionInfoSizeA(filename, None) # If no info in file -> empty string if not size: return '' # Create buffer res = create_string_buffer(size) # Load file informations into buffer res windll.version.GetFileVersionInfoA(filename, None, size, res) r = c_uint() l = c_uint() # Look for codepages windll.version.VerQueryValueA(res, '\\VarFileInfo\\Translation', byref(r), byref(l)) # If no codepage -> empty string if not l.value: return '' # Take the first codepage (what else ?) codepages = array.array('H', string_at(r.value, l.value)) codepage = tuple(codepages[:2].tolist()) # Extract information windll.version.VerQueryValueA(res, ('\\StringFileInfo\\%04x%04x\\' + info) % codepage, byref(r), byref(l)) return string_at(r.value, l.value)
print get_file_info(r'C:\WINDOWS\system32\calc.exe', 'FileVersion')
Атрибут Версия файла Windows Python
В прошлый раз я задал аналогичный вопрос, но это было связано с информацией о версиях svn. Теперь мне интересно, как запрашивать атрибуты окна «File version», например. dll. Я также обратил внимание на модули wmi и win32file без успеха.
7 ответов
import win32api #============================================================================== def getFileProperties(fname): #============================================================================== """ Read all properties of the given file return them as a dictionary. """ propNames = ('Comments', 'InternalName', 'ProductName', 'CompanyName', 'LegalCopyright', 'ProductVersion', 'FileDescription', 'LegalTrademarks', 'PrivateBuild', 'FileVersion', 'OriginalFilename', 'SpecialBuild') props = try: # backslash as parm returns dictionary of numeric info corresponding to VS_FIXEDFILEINFO struc fixedInfo = win32api.GetFileVersionInfo(fname, '\\') props['FixedFileInfo'] = fixedInfo props['FileVersion'] = "%d.%d.%d.%d" % (fixedInfo['FileVersionMS'] / 65536, fixedInfo['FileVersionMS'] % 65536, fixedInfo['FileVersionLS'] / 65536, fixedInfo['FileVersionLS'] % 65536) # \VarFileInfo\Translation returns list of available (language, codepage) # pairs that can be used to retreive string info. We are using only the first pair. lang, codepage = win32api.GetFileVersionInfo(fname, '\\VarFileInfo\\Translation')[0] # any other must be of the form \StringfileInfo\%04X%04X\parm_name, middle # two are language/codepage pair returned from above strInfo = <> for propName in propNames: strInfoPath = u'\\StringFileInfo\\%04X%04X\\%s' % (lang, codepage, propName) ## print str_info strInfo[propName] = win32api.GetFileVersionInfo(fname, strInfoPath) props['StringFileInfo'] = strInfo except: pass return props
Вау, отличная работа. Как ты вообще узнал материал StringFileInfo . это то, что мне нужно. большое спасибо.