Windows: Versionsinformationen von EXE-Dateien einlesen???

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Windows: Versionsinformationen von EXE-Dateien einlesen???

Beitragvon jens » Montag 22. November 2004, 20:54

Kommt man an die Datei Information herran, die man angezeigt bekommt, wenn man sich die "Eigenschaft" einer Datei anschaut?

Also:

Code: Alles auswählen

Eigenschaften / Version /
 -Dateiversion
 -Beschreibung
 -Copyright



EDIT:
Ah, hab gerade das gefunden:
"Using windll to extract version information from Windows files"
http://aspn.activestate.com/ASPN/Cookbo ... ipe/117219

EDIT2:
Naja, diese Beispiel setzt wieder ein paar Module und DLL's vorraus... :(
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Montag 22. November 2004, 23:20

Also eigentlich stehen die Informationen im "Klartext" in der EXE-Datei... Leider nicht ganz so "Klartext"...

Die Daten stehen fast am Ende der Datei... Jedoch kann ich mir vorstellen, das man mittels re. und ein paar IF-Abfragen unabhängig der Dateigröße/Position rausfiltern kann...

Ich hab jedoch Schwirigkeiten damit. Wenn man mit einem HEX-Editor eine Datei anschaut und zu diesen Daten scrollt, kann man sehen, das jeder Buchstabe durch ein NULL-Zeichne getrennt ist... Ich kann mir vorstellen, das es was mit UniCode-Formatierung zutun hat...

Hier hab ich mal ein Beispiel, der die richtige Position der Daten im Windows-Notepad v5.1.2600.2180 anzeigt:

Code: Alles auswählen

FileHandle = open( "c:\\windows\\Notepad.exe", "rb" )
RAWinfo = FileHandle.read()
FileHandle.close()

RAWinfo = RAWinfo[68430:69148]
print RAWinfo
print "".join( re.findall("\w",RAWinfo) )


Die Ausgabe des zweiten Prints sieht so aus:

Code: Alles auswählen

StringFileInfo040704B0LCompanyNameMicrosoftCorporation8FileDescriptionEditortFileVersion5126002180xpsp_sp2_rtm04080321580InternalNameNotepad2LegalCopyrightMicrosoftCorporationAlleRechtevorbehaltenOriginalFilenameNOTEPADEXEhProductNameBetriebssystemMicrosoftWindowsProductVersion5126002180
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Montag 22. November 2004, 23:28

Hier: http://p-nand-q.com/python/unicode_faq.html
Unter "Unicode in Dateien"

Dort kann man einen HEX-Auszug sehen, der mit dem Notepad.exe, was ich meine, übereinstimmt...

Also sind die Daten wahrscheinlich in Unicode hinterlegt?
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 23. November 2004, 00:39

Hi jens,

wenn jedes Zeichen aus 2 Byte besteht, dürfte es sich um "utf-16" handeln.


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Gast

Beitragvon Gast » Dienstag 23. November 2004, 12:58

Dookie hat geschrieben:wenn jedes Zeichen aus 2 Byte besteht, dürfte es sich um "utf-16" handeln.


Das hatte ich schon mal versucht, aber das funktionierte nicht richtig...
Allerdings, hab ich hier eine kleine Schäbige Variante gebaut:

Code: Alles auswählen

FileHandle = open( "c:\\Notepad.exe", "rb" )
RAWdata = FileHandle.read().replace("\x00","")
FileHandle.close()
print re.findall("CompanyName([A-Za-z ]+)", RAWdata )
print re.findall("FileDescription([A-Za-z ]+)", RAWdata )
print re.findall("FileVersion([\w. ]+)", RAWdata )
print re.findall("InternalName([A-Za-z ]+)", RAWdata )


Ergebnis:

Code: Alles auswählen

['Microsoft Corporation']
['Editort']
['5.1.2600.2180 ']
['Notepad']


Das dumme ist nur, das bei der Verionsinformation in Dateien, die Elementnamen ( bsp. CompanyName, FileDescription usw.) nicht "genormt" sind...
Ich denke nur Dateiversion, Beschreibung und Copyright sind fest drin, also zumindest macht das den Anschein, wenn man sich das Eigenschaft/Version-Kontextmenü zu einer Datei anschaut... Und die drei angaben würden für mich eigentlich reichen... Aber wenn man schon mal dran ist...
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 23. November 2004, 13:03

(Das oben war ich)

Anzumerken ist noch, das diese Lösung nicht 100% funktioniert wie man z.B. am Ergenis: ['Editort'] sehen kann... eigentlich sollte es natürlich nur "Editor" heißen, aber das anschließende "t" ist ja auch ein Buchstabe und wird somit von [A-Za-z ] gefunden...
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 23. November 2004, 13:43

Was hst Du versucht? Du löscht einfach die 0x00 bytes das is sicher keine saubere Lösung, wenn du die daten bekommst lass sie, mit unicode(text_in_utf16, "utf-16"), in utf-8-unicode wandeln und verwende sonst auch für alle textstrings unicode statt str, dann sollte es klappen.


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 23. November 2004, 16:32

Nein, das Beispiel mit dem .replace("\x00","") war nicht mein Unicode-Versuch, diesen hab ich ähnlich gemacht, wie dein Beispiel hier:
http://python.sandtner.org/viewtopic.php?p=10164#10164

Ich hab auch verschiedene durchprobiert "utf-8", "latin-1", "UTF-16LE" und "UTF-16" aber das klappte bei keinem richtig :(

Noch eine andere Frage... Wie kann ich bei .read() angeben, das nur etwas die letzten 1024 Bytes gelesen werden?
Denn ich denke, egal wie die Lösungs hinter aus sehen wird, ich denke ich muß immer die Daten analysieren. Nur, die für mich relevanten Daten liegen ja eh nur am Ende einer Datei... Somit ist es ja blödsinnig die ganze Datei zu durchsuchen...

Ich denke auch bei .read()[:1024] wird doch wohl erst die ganze Datei eingeladen und dann "gekürzt", oder?
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 23. November 2004, 17:34

Du kannst mit f.seek(-1024, 2) an die Stelle in der Datei springen und dann mit f.read(1024) die letzten 1024 Bytes lesen.

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 23. November 2004, 22:31

f.seek(-1024, 2) ist super! Danach, bauche ich aber nicht unbedingt mit f.read(1024) zu arbeiten... ein normales f.read() geht auch, er liest einfach von der Position bis zum Ende...

So, jetzt nochmal ein Test mit verschiedenen Codings, mit FileHandle = codecs.open( "Notepad.exe", "rb", encoding="XXX" )

utf-16le - UnicodeDecodeError: 'utf16' codec can't decode bytes in position 1644-1645: illegal encoding

utf-16 - UnicodeError: UTF-16 stream does not start with BOM

utf-8 - UnicodeDecodeError: 'utf8' codec can't decode byte 0x90 in position 2: unexpected code byte

latin-1 - UnicodeEncodeError: 'ascii' codec can't encode character u'\xb0' in position 30: ordinal not in range(128)
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 23. November 2004, 22:40

jo is klar, ich sagte auch das eingelesene dann mit unicode(text,'utf-16LE') in Python-Unicode wandeln lassen.

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Dienstag 23. November 2004, 22:44

Hmm.... Da verstehe ich dich jetzt leider nicht so ganz... Was meinst du mit dem "eingelesenen" ???

Ich hab es hier mal versucht:

Code: Alles auswählen

FileHandle = open( "Notepad.exe", "rb" )
FileHandle.seek(-2048, 2)
RAWdata = FileHandle.read()
FileHandle.close()
print len(RAWdata)

print unicode(RAWdata,'utf-16LE')

Code: Alles auswählen

UnicodeEncodeError: 'ascii' codec can't encode character u'\u0300' in position 22: ordinal not in range(128)


Ich hab festgestellt, das die Daten zumindest mit \x01 eingeschlossen sind... Nun versuche ich gerade mit RE nur A-Za-z0-9 die zwischen \x01 stehen rauszufiltern... Leider noch ohne Erfolg...
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Dienstag 23. November 2004, 22:56

such doch einfach nach '\0x01' ohne re und hole die strings dann anhand der Positionen raus, oder nimm einfach split():

Code: Alles auswählen

FileHandle = open( "Notepad.exe", "rb" )
FileHandle.seek(-2048, 2)
RAWdata = FileHandle.read()
FileHandle.close()
strings = RAWdata.split('\0x01')[1:] # im ersten string steht nur muell
unis = [unicode(x, "utf-16LE") for x in strings]
for i in unis:
    print i



Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 24. November 2004, 09:01

Mist, ich hab weitere Tests gemacht und einige Dateien nach "StringFileInfo" mittels .rfind() durchsucht, mit diesem String werden wohl die gesuchten Information "eingeleitet"...
Zwar ist die Position des Strings fast immer am Ende der Datei, aber nicht immer :(

Ein extrem Beispiel ist soffice.exe von OpenOffice... Dort befindet sich der String ca. in der hälfte der Datei...

Naja, nun muß ich erstmal Testen, ob nach "StringFileInfo" wirklich die Informationen kommen... Oder ob es evtl. "zufällig" in Dateien vorkommt...

EDIT: Jep, sind die richtigen Info's... Diese fangen wohl mit "StringFileInfo" an und höhren mit "VarFileInfo" auf... Das ist ideal für RE


EDIT2: Schade... Die Passage fägt zwar immer mit "StringFileInfo" an, höhrt aber leider nicht immer mit "VarFileInfo" auf :( Also ein re.findall("StringFileInfo(.*?)VarFileInfo",...) klappt somit nicht...
Benutzeravatar
jens
Moderator
Beiträge: 8458
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Beitragvon jens » Mittwoch 24. November 2004, 09:30

Hier nochmal ein versuch:


Code: Alles auswählen

import os

def FindAllVerInfo( FileName ):
    FileHandle = open( FileName, "rb" )
    RAWdata = FileHandle.read().replace("\x00","")
    FileHandle.close()

    POS = RAWdata.rfind( "StringFileInfo" )

    if POS == -1:
        print "* NOT FOUND *"
        return

    EndPOS = RAWdata.rfind( "VarFileInfo" )
    if EndPOS == -1:
        EndPOS = POS+500

    RAWdata = RAWdata[ POS:EndPOS]

    for i in RAWdata.split("\x01")[2:]:
        print i[:-2]


Endungen = [".exe",".dll"]

for Verz, VerzList, DateiListe in os.walk("C:\\"):
    for Datei in DateiListe:
        FileExt = os.path.splitext(Datei)[1]
        if FileExt in Endungen:
            print "\n>",Datei
            Datei = Verz+os.sep+Datei
            FindAllVerInfo( Datei )


Bsp.:

Code: Alles auswählen

> FlashPlayerW.dll
CompanyNameMacromedia, Inc.
FileDescriptionMacromedia Flash Player 6.0  r23
FileExtentsswf|spl
FileOpenNameMacromedia Flash movie (*.swf)|FutureSplash movie (*.spl)
FileVersion6,0,23,0
InternalNameMacromedia Flash Player 6.0
LegalCopyrightCopyright © 1996-2002 Macromedia, Inc.
LegalTrademarksMacromedia Flash Player
OriginalFilenameauthplay.dll
ProductNameShockwave Flash
ProductVersion6,0,23,

> NPSWF32.dll
CompanyNameMacromedia, Inc.
FileDescriptionShockwave Flash 6.0  r68
FileExtentsswf|spl
FileOpenNameMacromedia Flash movie (*.swf)|FutureSplash movie (*.spl)
MIMETypeapplication/x-shockwave-flash|application/futuresplash
ProductNameShockwave Flash
FileVersion6,0,68,0
InternalNameMacromedia Flash Player 6.0
LegalCopyrightCopyright © 1996-2002 Macromedia, Inc.
LegalTrademarksMacromedia Flash Player
OriginalFilenamenpswf32.dll
ProductVersion6,0,68,


Das Blöde ist nur, das Eintrag:Wert nicht mehr getrennt sind... Also bei CompanyNameMacromedia, Inc. ist kein Leerzeichen zwischen CompanyName und Macromedia, Inc. :(

Das liegt natürlich an meiner Art die Datei per .replace("\x00","") zu verschandeln... Aber mit Encodings hat es bisher ja nie geklappt :(

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder