2009-02-24 10 views
20

L'ultima volta che ho fatto una domanda simile ma che riguardava informazioni sulla versione di svn. Ora mi chiedo come interrogare l'attributo "Versione file" di Windows ad es. una dll. Ho prestato attenzione anche ai moduli wmi e win32file senza successo.Attributo versione file di Python windows

risposta

4

Ho trovato questa soluzione nel sito "timgolden". Funziona bene.

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

Meglio aggiungere una prova/tranne nel caso in cui il file non abbia attributo numero di versione.

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) 

Cheers!

10

È possibile utilizzare il modulo pyWin32 da 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

funziona perfettamente e più semplice di tutte le soluzioni! Grazie. – 0x1mason

+0

C'è un modo per ottenere anche la descrizione del file? Non ho visto alcun metodo in FileSystemObject che lo faccia :( –

+0

Ha funzionato come un incantesimo. Grazie !! – Suneelm

21

Ecco una funzione che legge tutti attributi di file come un dizionario:

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, ottimo lavoro. Come hai scoperto la trama di StringFileInfo .. questo è quello che mi serve. Grazie mille – iridescent

+1

Per chi se ne importa, 65536 è mezzo DWORD (2 ** 16) – theannouncer

10

Ecco una versione che funziona anche in non di Windows ambienti, utilizzando il 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

Lo trovo perfettamente nel lavoro, ma ci vogliono oltre 10 secondi per farlo su un 30mb exe :( – Steve

+3

Ho capito dalla fonte che si può tagliare da 10 a 1 s/2s analizzando solo la directory delle risorse, woo !: 'pe = pefile.PE (percorso, fast_load = True) pe.parse_data_directories (directory = [pefile.DIRECTORY_ENTRY ['IMAGE_DIRECTORY_ENTRY_RESOURCE']])' – Steve

+0

Bello, volevo suggerire una cosa del genere – flocki

2

Ecco una versione che non richiede alcuna libreria aggiuntiva. Non ho potuto usare Win32API come tutti gli aveva suggerito:

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

Solo copiato qui nel caso in cui l'originale scompare.

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) 

usati in questo modo:

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

'WindowsError: eccezione: violazione di accesso che legge 0x0000000082E47858' quando si ottengono le codepage.' string_at (r.value, l.value) 'fallisce lì :( – ewerybody

Problemi correlati