AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Dateibeschreibung aus Ressource auslesen

Dateibeschreibung aus Ressource auslesen

Ein Thema von Luckie · begonnen am 15. Aug 2005 · letzter Beitrag vom 15. Aug 2005
Antwort Antwort
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#1

Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 02:23
Ich benutze folgenden Code, um die Dateiversion aus der Ressource auszulesen:
Delphi-Quellcode:
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;
Wie man sieht, versuche ich auch an die Beschreibung zu kommen, nur klappt das nicht so ganz. Diese Zeile
Delphi-Quellcode:
// Description
if VerQueryValue(VerInfo, '\VarFileInfo\Translation', Pointer(VerValue), VerValueSize) then
liefert immer False zurück. Kann mir da mal bitte jemand helfen das hinzubekommen? Danke.

Sorry, es ist Zeile 39, die immer False zurückliefert.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#2

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 03:45
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 ... ich meine du schreibst Tutorials, willst anderen was beibringen. Klar kann nicht jeder alles wissen, aber die Doku lesen ...

Delphi-Quellcode:
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;
Wenn du GMEM_FIXED benutzt, brauchst du auch kein GlobalLock() - nur so nebenbei.

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.
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 04:17
Ich habe die Doku gelesen, nur hatte ich Probleme mit dem umsetzen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#4

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 15:16
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:
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;
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).

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:
...
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
 }
}
Bei einem Viewer müsstest du den memory block anhand der definierten Strukturen parsen, aber dann hättest du sicher nicht ParamStr(0) verwendet...

Grüße vom marabu
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 15:19
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#6

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 15:33
Zitat von Luckie:
Ich benutze folgenden Code, um die Dateiversion aus der Ressource auszulesen:
Ich kann da die JCL nur wärmstens empfehlen!!
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.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#7

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 15:47
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.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#8

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 16:05
Zitat von marabu:
aber immer noch deutlich weniger Aufwand als Olli (abgesehen von dem Fehler).
ich hab'nen Fehler gemacht? Tut mir das nicht an! Was habe ich dir getan, marabu, daß du das hier öffentlich sagen mußt, daß ich einen Fehler gemacht habe? *schnief* *szene-mach*


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
  Mit Zitat antworten Zitat
marabu

Registriert seit: 6. Apr 2005
10.109 Beiträge
 
#9

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 16:16
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
  Mit Zitat antworten Zitat
Olli
(Gast)

n/a Beiträge
 
#10

Re: Dateibeschreibung aus Ressource auslesen

  Alt 15. Aug 2005, 16:50
Zitat von marabu:
Krieg dich wieder ein, Olli - ich hatte die Klammer falsch gesetzt.
[...]
Reicht das für eine Rehabilitation?
*letzte-krokodilsträne-rausdrück* ... na gut, weil du's bist

War doch nur Spaß

Mit fröhlichem Gruß,
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:26 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz