![]() |
Dateibeschreibung aus Ressource auslesen
Ich benutze folgenden Code, um die Dateiversion aus der Ressource auszulesen:
Delphi-Quellcode:
Wie man sieht, versuche ich auch an die Beschreibung zu kommen, nur klappt das nicht so ganz. Diese Zeile
function GetVersion(var VersionString, Description: string): DWORD;
var VerInfoSize : DWORD; hMem : THandle; VerInfo : Pointer; VerValueSize : DWORD; VerValue : PVSFixedFileInfo; LangID : string; Dummy : DWORD; s : string; begin result := 0; VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), Dummy); if VerInfoSize <> 0 then begin hMem := GlobalAlloc(GPTR, VerInfoSize); if hMem <> 0 then begin VerInfo := GlobalLock(hMem); try // Version if GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo) then begin if VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize) then begin with VerValue^ do begin VersionString := Format('%d.%d.%d.%d', [dwFileVersionMS shr 16, dwFileVersionMS and $FFFF, dwFileVersionLS shr 16, dwFileVersionLS and $FFFF]); end; end else VersionString := ''; // Description if VerQueryValue(VerInfo, '\VarFileInfo\Translation', Pointer(VerValue), VerValueSize) then begin LangId := IntToHex(LoWord(PLongInt(VerInfo)^), 4) + IntToHex(HiWord(PLongInt(VerInfo)^), 4); s := '\StringFileInfo\' + LangId + '\FileDescription'; if VerQueryValue(VerInfo, PChar(s), Pointer(VerValue), VerValueSize) then Description := PChar(VerValue); end else Description := ''; end; finally GlobalUnlock(hMem); GlobalFree(hMem); end; end else // GlobalAlloc result := GetLastError; end else // GetFileVersionInfoSize result := GetLastError; end;
Delphi-Quellcode:
liefert immer False zurück. Kann mir da mal bitte jemand helfen das hinzubekommen? Danke.
// Description
if VerQueryValue(VerInfo, '\VarFileInfo\Translation', Pointer(VerValue), VerValueSize) then Sorry, es ist Zeile 39, die immer False zurückliefert. |
Re: Dateibeschreibung aus Ressource auslesen
Als erstes würde ich einen anderen Namen für die Funktion vorschlagen, da GetVersion() bekanntlich eine ältliche Kernel32-API ist, die man nutzt um die Windowsversion zu ermitteln ;)
Keine Ahnung was du mit dem Aufruf bezweckst, aber im PSDK steht es ganz deutlich beschrieben. Und genau das scheinst du zu ignorieren. Es steht dort eindeutig, daß es sich um ein Array von DWORDs handelt. Was immer dich auch geritten hat dort eine komplett andere Struktur anzugeben, es ist falsch. Manchmal bringt es mich zum Grübeln, wenn du einerseits Leute im Forum zusammensch.... und andererseits selber nicht die Doku liest :gruebel: ... ich meine du schreibst Tutorials, willst anderen was beibringen. Klar kann nicht jeder alles wissen, aber die Doku lesen ... :roll:
Delphi-Quellcode:
Wenn du GMEM_FIXED benutzt, brauchst du auch kein GlobalLock() - nur so nebenbei.
function GetVersionInfo(var VersionString, Description: String): DWORD;
type PDWORDArr = ^DWORDArr; DWORDArr = array[0..0] of DWORD; var VerInfoSize: DWORD; VerInfo: Pointer; VerValueSize: DWORD; VerValue: PVSFixedFileInfo; LangInfo: PDWORDArr; LangID: DWORD; Desc: PChar; s: String; i: Integer; begin result := 0; VerInfoSize := GetFileVersionInfoSize(PChar(ParamStr(0)), LangID); if VerInfoSize <> 0 then begin VerInfo := Pointer(GlobalAlloc(GPTR, VerInfoSize)); if Assigned(VerInfo) then try if GetFileVersionInfo(PChar(ParamStr(0)), 0, VerInfoSize, VerInfo) then begin if VerQueryValue(VerInfo, '\', Pointer(VerValue), VerValueSize) then begin with VerValue^ do begin VersionString := Format('%d.%d.%d.%d', [dwFileVersionMS shr 16, dwFileVersionMS and $FFFF, dwFileVersionLS shr 16, dwFileVersionLS and $FFFF]); end; end else VersionString := ''; // Description if VerQueryValue(VerInfo, '\VarFileInfo\Translation', Pointer(LangInfo), VerValueSize) then begin if (VerValueSize > 0) then begin // Divide by element size since this is an array VerValueSize := VerValueSize div sizeof(DWORD); // Number of language identifiers in the table (********************************************************************) for i:= 0 to VerValueSize-1 do begin // Swap words of this DWORD LangID := (LoWord(LangInfo[i]) shl 16) or HiWord(LangInfo[i]); Writeln(Format('Habe gefunden: %8.8x', [LangID])); // Query value ... if VerQueryValue(VerInfo, @Format('\StringFileInfo\%8.8x\FileDescription', [LangID])[1], Pointer(Desc), VerValueSize) then Description := Desc; end; (********************************************************************) end; end else Description := ''; end; finally GlobalFree(THandle(VerInfo)); end else // GlobalAlloc result := GetLastError; end else // GetFileVersionInfoSize result := GetLastError; end; Du solltest dir auch klarmachen, daß es mehrere Blöcke geben kann. Deswegen ist es irrsinnig davon auszugehen, daß es nur einen gibt, wie du das in deinem Code zu tun schienst. Ich habe die FOR-Schleife oben hervorgehoben, damit du siehst was ich meine. Es macht also keinen Sinn irgendeinen Wert anzufordern ohne genau zu spezifizieren welchen du willst. Ich würde dir empfehlen noch einen Parameter an die Funktion zu übergeben und dann auf diesen zu testen (innerhalb der FOR-Schleife und bevor du die Stringvariable Description belegst). Ansonsten als Standardwert 0 übergeben, sollte eigentlich gehen, hab's aber nicht getestet. |
Re: Dateibeschreibung aus Ressource auslesen
Ich habe die Doku gelesen, nur hatte ich Probleme mit dem umsetzen.
|
Re: Dateibeschreibung aus Ressource auslesen
Hallo Luckie,
da ich bei meinen Programmen weiß, wie der resource file aufgebaut ist, kann ich auf die Auswertung von VarFileInfo\Translation verzichten:
Delphi-Quellcode:
Mit diesem Code lese ich genau die Strings aus, die auf der Zielmaschine sinnvoll sind - und die ich vorher in meinen resfile geschrieben habe. Da auch du die Resourcen von ParamStr(0) untersuchst, treibst du relativ viel Aufwand zur Ermittlung der language specs - aber immer noch deutlich weniger Aufwand als Olli (abgesehen von dem Fehler).
procedure GetFileVersionLanguage(var FileVersionLanguage: string);
var lcid: cardinal; cp: string; begin lcid := GetUserDefaultLCID; SetLength(cp, GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, nil, 0)); GetLocaleInfo(lcid, LOCALE_IDEFAULTANSICODEPAGE, @cp[1], Length(cp)); FileVersionLanguage := IntToHex(lcid, 4) + IntToHex(StrToInt(cp), 4); end; Wenn du einen resource viewer bauen willst, dann wird der Aufwand noch viel größer sein müssen. Nicht nur, dass mehrere language/codepage Paare spezifiziert sein können, die zugehörigen strings können mit deiner Methode eventuell unerreichbar sein, denn auch sowas wird kompiliert:
Code:
Bei einem Viewer müsstest du den memory block anhand der definierten Strukturen parsen, aber dann hättest du sicher nicht ParamStr(0) verwendet...
...
FILETYPE VFT_APP { BLOCK "StringFileInfo" { VALUE "CompanyName", "NameOfCompany\000" VALUE "FileDescription", "Description\000" VALUE "FileVersion", "1.2.3.4\000" VALUE "InternalName", "InternalName\000" VALUE "LegalCopyright", "Copyright\000" VALUE "LegalTrademarks", "Trademark\000" VALUE "OriginalFilename", "OriginalFileName\000" VALUE "ProductName", "ProductName\000" VALUE "ProductVersion", "1.0.0.0\000" VALUE "Comments", "Comments\000" } BLOCK "VarFileInfo" { VALUE "Translation", 0, 0 } } Grüße vom marabu |
Re: Dateibeschreibung aus Ressource auslesen
Nein, es ist schon nur für mein eigenes Programm. Ich will mir damit ersparen die Versionsinfo und die Beschreubung im Code und in der Ressource immer synchron halten zu müssen. Jetzt muss ich nur an die Ressource denken, der Rest in der Aboutbox, geht dann automatisch. Ist also nur eine Arbeitserleichterung für mich.
|
Re: Dateibeschreibung aus Ressource auslesen
Zitat:
Ich weiss ja, da du gerne deine eigenen Units und abgespeckten Klassen fabrizierst, aber aus der Unit JclFileUtils, Klasse TJclFileVersionInfo kann man auch prima abkupfern. Ich habe lange im Internet recherchiert; in Punkto Qualität und Funktionsumfang gibt's nichts besseres als diese Klasse. |
Re: Dateibeschreibung aus Ressource auslesen
Da ich, wie du schon selber sagst, lieber meinen eigenen Mist verwende, fällt für private nonVCl Projekte die JCL raus. ;) Aber danke für den Hinweis. :thumb:
|
Re: Dateibeschreibung aus Ressource auslesen
Zitat:
:mrgreen: Nee, sag mal, wo habe ich nen Fehler gemacht? Will's schon wissen. @Luckie: Du solltest wirklich mal öfter in die JCL gucken. Da gibt es ja nun nicht nur Klassen ;) |
Re: Dateibeschreibung aus Ressource auslesen
Krieg dich wieder ein, Olli - ich hatte die Klammer falsch gesetzt.
marabu wollte eigentlich folgendes geschrieben haben treibst du (abgesehen von dem Fehler) relativ viel Aufwand zur Ermittlung der language specs - aber immer noch deutlich weniger Aufwand als Olli Reicht das für eine Rehabilitation? Zerknirschte Grüße vom marabu |
Re: Dateibeschreibung aus Ressource auslesen
Zitat:
War doch nur Spaß :mrgreen: Mit fröhlichem Gruß, |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:14 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz