![]() |
StringFileInfo/VarFileInfo für Dateiversion schreiben
Liste der Anhänge anzeigen (Anzahl: 2)
Guten Morgen,
nachdem es mir mit der Hilfe von Zacherl gelungen ist, die Versionsinformation mittels UpdateResource zu einer Datei hinzuzufügen, stehe ich nun vor dem Problem die StringFileInfo zu setzen bzw. zu schreiben. Auf den msdn Seiten sind die nötigen Strukturen ( ![]() ![]() Genauso muss auch die VarFileInfo geschrieben werden. Ohne diese beiden Informationen wird der Reiter unter Windows nicht richtig dargestellt. (siehe Anhang) Hat jemand dies schonmal getan, wenn ja, mit welcher Technik. Ich habe bei meinen Recherchen einen Ansatz gefunden, der Streams verwendetet, leider ist mir die URL abhanden gekommen. Würde mich auf Antworten freuen. Gruß Mazel |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Die Strukturen werden einfach hintereinander "geklebt".
Man kann keine normalen Pascal Records verwenden, sondern man braucht einen Speicherblock (mit GetMem) und baut dann dort die Strukturen auf. Die Herausforderung ist dann, dass wLength von VS_VERSIONINFO auch alle weiteren StringFileInfo Blöcke berücksichtigen muss. |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Hallo und danke für deine Antwort.
Mit GetMem arbeiten, ok. Das heißt in dem Fall für jeden Block den ich hizufüge oder von vorn herein soviel reservieren, wie cih für alles benötige, was zur Folge habe muss, dass ich vorher die Größe brauch. Hast du eventuell ein Beispiel? Ich habe mir gestern eine Variante überlegt, die funktioniert aber nicht "das Wahre" ist. Ich habe aus ResHacker eine binäre Datei erstellt die eine vollständige VERSIONINFO Struktur mit allen unterstrukturen enthält. Diese lade über ein FileStream in mein Programm und übergebe diese dann per UpdateResource an die jeweilige Anwendung. Nachteil ist aber dabei, dass ich danach wieder die Werte ändern muss und so wieder vor dem Problem stehe. Hier mal der Code dazu, eventuell kann man mir daraus auch einen weiteren Tipp geben.
Delphi-Quellcode:
Gruß
{--[AddResourceStruture]-------------------------------------------------------}
function AddResourceStruture(ExecutableFile: String): Boolean; var FileStream : TFileStream; ResourceHandle : THandle; DataLength : Cardinal; Data : Pointer; Path : String; begin Result := False; Path := ExtractFilePath(ParamStr(0)); if not EndsWith(Path, '\') then Path := Path + '\'; Path := Path + 'Resource\VSResource.bin'; ResourceHandle := BeginUpdateResource(PChar(ExecutableFile), False); if (ResourceHandle <> 0) then begin FileStream := TFileStream.Create(Path, fmOpenRead); FileStream.Seek(0, soFromBeginning); DataLength := FileStream.Size; try GetMem(Data, DataLength); FileStream.Read(Data^, DataLength); FileStream.Free; Result := True; // for german language only - 1031 if not UpdateResource(ResourceHandle, RT_VERSION, MakeIntResource(1), 1031, Data, DataLength) then Result := False; if not EndUpdateResource(ResourceHandle, False) then Result := False; finally FreeMem(Data); end; ShowMessage(SysErrorMessage(GetLastError)); end; end; Mazel |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Zitat:
Eine Möglichkeit wäre, mit den innersten String Structure zu beginnen und diese dann zu einer StringTable Structure zusammenzubauen, die dann wiederum zur StringFileInfo Structure aufgebaut wird. Hier völlig ungetestet als Anregung:
Delphi-Quellcode:
Damit kann man jetzt mehrere String Structures zusammen verketten:
function BuildStringStructure(Key, Value : Widestring):Ansistring;
var p : PInteger; begin key := key + #0; // Terminierung mit 0x0000 if odd(length(key)) then key := key + #0; // auf 32-bit boundary bringen SetLength(result, 2 + 2 + 2+ 2*Length(key) + 2 * Length(Value)) p := PInteger(PChar(result)); p^ := length(Result); // WORD wLength befüllen Inc(p); p^ := length(Value) * 2; // WORD wValueLength befüllen Inc(p); p^ := 1; // WORD wType Inc(p); // jetzt muss noch Key und Value in den Resultstring kopiert werden (mit Move()) // ich spar mir das mal end;
Delphi-Quellcode:
Jetzt muss das zu einer StringTable Structure aufgebaut werden:
data := BuildStringStructure('Comments', 'ein Test') + BuildStringStructure('CompanyName', 'DP') + ....
Delphi-Quellcode:
Wenn man soweit ist, ist der Aufbau der StringFileInfo Structure relativ einfach:
function BuildStringTableStructure(Key:WideString; const Children:Ansistring):AnsiString;
Delphi-Quellcode:
function BuildStringFileInfoStructure(Key:WideString; const Children:Ansistring):AnsiString;
begin Result := BuildStringTableStructure('StringFileInfo', Children); end; |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Guten Abend,
danke für diese schönen Tipps. Ich habe jetzt schonmal versucht etwas zu kreieren, bin aber bis jetzt noch zu keinem Erfolg gekommen und zum zeigen muss ich noch einiges zusammenfassen und weiter ausprobieren. :roll: Es ist eben nicht einfach diese Struktur zusammen zubauen :) Wenn ich dein Code als Grundlage nehme verarbeite ich am Ende den AnsiChar. Ich bräuchte ja aber den Pointer, damit ich diesen an Children weitergeben kann. Btw.: ich hatte von Zacherl folgende Strukturen bekommen, die ich ein wenig aufgebessert habe, damit es funktioniert.
Delphi-Quellcode:
Anfangs gab es Probleme in der Reihenfolge, nachdem ich das geändert hatte konnte ich die VERSIONINFO schreiben, aber die children gehen bis heute noch nicht, da tu ich mich wohl etwas schwer.
type
TFIXEDFILEINFO = packed record dwSignature: DWord; dwStrucVersion: DWord; dwFileVersionMS: DWord; dwFileVersionLS: DWord; dwProductVersionMS: DWord; dwProductVersionLS: DWord; dwFileFlagsMask: DWord; dwFileFlags: DWord; dwFileOS: DWord; dwFileType: DWord; dwFileSubtype: DWord; dwFileDateMS: DWord; dwFileDateLS: DWord; end; TVERSIONSTRING = packed record wLength: Word; wValueLength: Word; wType: Word; {$IFDEF D12ORABOVE} szKey: String; {$ELSE} szKey: WideString; {$ENDIF} Padding: TWordArray; {$IFDEF D12ORABOVE} Value: String; {$ELSE} Value: WideString; {$ENDIF} end; TVERSIONSTRINGTABLE = packed record wLength: Word; wValueLength: Word; wType: Word; {$IFDEF D12ORABOVE} szKey: Array[0..8] of Char; {$ELSE} szKey: Array[0..8] of WideChar; {$ENDIF} Padding: TWordArray; Children: array of TVERSIONSTRING; end; TSTRINGFILEINFO = packed record wLength: Word; wValueLength: Word; wType: Word; {$IFDEF D12ORABOVE} szKey: Array[0..14] of Char; {$ELSE} szKey: Array[0..14] of WideChar; {$ENDIF} Padding: TWordArray; Children: Array of TVERSIONSTRINGTABLE; end; TVERSIONINFO = packed record wLength: Word; wValueLength: Word; wType: Word; szKey: Array[0..15] of WideChar; Padding1: Word; Value: TFIXEDFILEINFO; Padding2: Word; Children: Array of TSTRINGFILEINFO; end; Gruß Mazel |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Ich hatte es damals so gemacht, dass ich zuerst die Strukturen aufgebaut habe, wobei ich die Größe erst einmal komplett umberechnet gelassen habe.
In einem zweiten Durchgang habe ich dann für jeden Zweig jeweils von innen nach außen die Größe berechnet. Bei dieser Struktur ist dies ja gar nicht mal so schwer, da die Anzahl der Zweige statisch gestaltet ist. |
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Zitat:
Dabei werden die beteiligten Stringstücke in einen neuen String kopiert. Mit der Technik von Zacherl könnte man sich die kopierei sparen, aber so ist es viel eleganter. alles ungetestet:
Delphi-Quellcode:
und dann die Daten quasi von Innen nach Aussen aufbauen:
function BuildStringStructure(Key, Value : Widestring):Ansistring;
var p : PInteger; begin key := key + #0; // Terminierung mit 0x0000 if odd(length(key)) then key := key + #0; // auf 32-bit boundary bringen SetLength(result, 2 + 2 + 2+ 2*Length(key) + 2 * Length(Value)) p := PInteger(PChar(result)); p^ := length(Result); // WORD wLength befüllen Inc(p); p^ := length(Value) * 2; // WORD wValueLength befüllen Inc(p); p^ := 1; // WORD wType Inc(p); // Key und Value auf den Ergebnisstring kopieren Move(key[1], p^, length(key)*2); Inc(p, length(key)*2); Move(Value, p^, length(value)*2); // hoffentlich war die Längenberechnung von result richtig ;-) end; function BuildStringTableStructure(Key:WideString; const Children:Ansistring):AnsiString; var p : PInteger; begin key := key + #0; // Terminierung mit 0x0000 if odd(length(key)) then key := key + #0; // auf 32-bit boundary bringen SetLength(result, 2 + 2 + 2+ 2*Length(key)); // wird später noch länger... p := PInteger(PChar(result)); p^ := length(Result) + length(Children); // WORD wLength befüllen Inc(p); p^ := length(Children) * 2; // WORD wValueLength befüllen Inc(p); p^ := 1; // WORD wType Inc(p); Move(key[1], p^, length(key)*2); // einfach den übergebenen Children-Datenblock hinten anhängen Result := Result + Children; end; function BuildStringFileInfoStructure(const Children:Ansistring):AnsiString; begin Result := BuildStringTableStructure('StringFileInfo', Children); end; function BuildVarSructure(Value : Widestring):Ansistring; begin Result := BuildStringStructure('Translation', Value); end;
Delphi-Quellcode:
Jetzt fehlt nur noch die VS_VERSIONINFO Structure:
data := BuildStringStructure('Comments', 'ein Test') + BuildStringStructure('CompanyName', 'DP') + ....;
data := BuildStringTableStructure(LANG_CODE_8BYTES, data); data := BuildStringFileInfoStructure(data);
Delphi-Quellcode:
function BuildVersionInfoStructure(const fixedinfo:TFIXEDFILEINFO;const Children:Ansistring):AnsiString;
|
Re: StringFileInfo/VarFileInfo für Dateiversion schreiben
Hallo,
in dem Zusammhang habe ich eine Frage zur LCID. In ganz vielen Beiträgen im Internet wird ja beschrieben wie man seine Versionsinformationen in einer Textdatei zu pflegen. Wir haben sie "Version.RC" genannt und folgenden Block drin BLOCK "VarFileInfo" { VALUE "Translation", 1031, 1252 } Viele der genannten Seiten haben anstattt "1031" den Wert "1033" drin. Warum? Bei einigen Projekten hier war auch bei uns "1033" drin. Windows schluckt das und zeigt im Windows-Explorer die Infos richtig an. Heute haben wir eine Funktion gesucht zum Auslesen der Versionsinformationen und sind dabei über ![]() Der Code funktioniert mit "1031, 1252" sehr gut, mit "1033, 1252" liefert er Schrott zurück. Ich vermute dass der Grund ist, dass die LCID nicht zur Codepage passt. Weiss hier jemand mehr? Gruß |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:49 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