2009-02-24 12 views
20

Das letzte Mal fragte ich eine ähnliche Frage, aber das war über SVN verwandte Versionsinformationen. Jetzt frage ich mich, wie man Windows "Dateiversion" -Attribut über zB abfragt. eine DLL. Ich habe auch ohne Erfolg auf wmi und win32file Module geachtet.Python Windows Datei Version Attribut

Antwort

4

Ich fand diese Lösung bei "timgolden" Website. Funktioniert gut.

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)]) 
18

Lieber einen Versuch hinzufügen/außer für den Fall, dass die Datei keine Versionsnummer Attribut hat.

filever.py


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

yourscript.py:


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) 

Prost!

10

Sie können das pyWin32 Modul von http://sourceforge.net/projects/pywin32/:

from win32com.client import Dispatch 

ver_parser = Dispatch('Scripting.FileSystemObject') 
info = ver_parser.GetFileVersion(path) 

if info == 'No Version Information Available': 
    info = None 
+1

funktioniert perfekt und einfachste aller Lösungen! Vielen Dank. – 0x1mason

+0

Kann ich die Dateibeschreibung auch irgendwie bekommen? Ich habe keine Methode in FileSystemObject gesehen, die das tut :( –

+0

Arbeitete wie ein Charme. Vielen Dank! – Suneelm

21

Hier ist eine Funktion, die alle Datei als Wörterbuch-Attribute lautet:

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 = {'FixedFileInfo': None, 'StringFileInfo': None, 'FileVersion': None} 

    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 
+1

Wow, tolle Arbeit. Wie hast du sogar die StringFileInfo Zeug .. das ist was ich brauche. Vielen Dank. – iridescent

+1

Für diejenigen, die sich interessieren, 65536 ist ein halbes DWORD (2 ** 16) – theannouncer

10

Hier ist eine Version, die in Nicht-Windows funktioniert auch Umgebungen mit dem pefile-module:

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" 
+0

Ich finde das perfekt, aber es dauert über 10s, um es auf einer 30mb exe zu tun :( – Steve

+3

Ich habe herausgefunden, aus der Quelle, die Sie schneiden können Diese 10s bis zu 1s/2s durch Parsing nur das Ressourcenverzeichnis, woo !: 'pe = pefile.PE (Pfad, fast_load = True) pe.parse_data_directories (Verzeichnisse = [pefile.DIRECTORY_ENTRY ['IMAGE_DIRECTORY_ENTRY_RESOURCE']])' – Steve

+0

Nice! Ich wollte so etwas vorschlagen. – flocki

2

Hier ist eine Version, die keine zusätzlichen Bibliotheken benötigt. Ich konnte nicht verwenden win32api wie jeder vorgeschlagen hatte:

Von: https://mail.python.org/pipermail//python-list/2006-November/402797.html

Nur hier im Fall kopiert das Original verloren geht.

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) 

wie so verwendet:

print get_file_info(r'C:\WINDOWS\system32\calc.exe', 'FileVersion') 
+0

'WindowsError: Ausnahme: Zugriffsverletzung beim Lesen der Codepages 0x0000000082E47858 zu lesen.' string_at (r.value, l.value) 'scheitert dort :( – ewerybody