madRes - Change properties of executables
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
madRes - Change properties of executables
How do I use madRes to change properties of executable files, like Version, Copyright, Author, Description, ecc.?
P.S.
The file is build by my own software, so there are no copyright violations!
P.S.
The file is build by my own software, so there are no copyright violations!
Basically you need to replace the version information resource. madRes allows you to do that, but madRes doesn't know the format of the version information resource. So it's up to you to create a proper data block with the correct format. I think you can find some sources on the net for that purpose.
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
That's my preliminary-code (no optimization, just trial):
It does nothing... I know there must be something wrong (well, more than just "nothing"!) in this line:
but I have no idea of the real parameters to pass, mainly "size" and "data".
Code: Select all
procedure TFormMain.btnChangePropsClick(Sender: TObject);
const
MaxVersionKeys = 9;
VersionKeyNames: array [0..MaxVersionKeys] of String =
('CompanyName', 'FileDescription', 'FileVersion', 'InternalName',
'LegalCopyright', 'LegalTrademarks', 'OriginalFilename',
'ProductName', 'ProductVersion', 'Comments');
var
StandardKeys: array [0..MaxVersionKeys] of String;
VersionInfo : String;
LangCharset : String;
InfoAvailable: Boolean;
ThisInfo: Integer;
InfoLength: UINT;
Len: DWORD;
Handle: DWORD;
PCharset: PLongInt;
strSourceFile: String;
dwH: dword;
begin
try
if (FileExists(Self.labedtSourceFile.Text)) then begin
strSourceFile := Self.labedtSourceFile.Text;
// Get size of version info
Len := GetFileVersionInfoSize(PChar(strSourceFile), Handle);
// Allocate VersionInfo buffer size
SetLength(VersionInfo, Len + 1);
// Get version info
if GetFileVersionInfo(PChar(strSourceFile), Handle, Len, Pointer(VersionInfo)) then begin
// Get translation info for Language / CharSet IDs
if VerQueryValue(Pointer(VersionInfo), '\VarFileInfo\Translation', Pointer(PCharset), InfoLength) then begin
LangCharset := Format('%.4x%.4x', [LoWord (PCharset^), HiWord (PCharset^)]);
InfoAvailable := True;
// Get standard version information
for ThisInfo := 0 to MaxVersionKeys do begin
StandardKeys[ThisInfo] := 'EDITED';
end;
dwH := BeginUpdateResourceW(PWideChar(WideString(strSourceFile)), False);
for ThisInfo := 0 to MaxVersionKeys do begin
UpdateResourceW(dwH, PWideChar(RT_VERSION), PWideChar(StandardKeys[ThisInfo]), 0, nil, Len);
end;
EndUpdateResourceW(dwH, False);
end;
end;
end else begin
ShowMessage('File eseguibile non selezionato o inesistente.');
end;
except
on E:Exception do
ShowMessage(E.Message);
end;
Code: Select all
UpdateResourceW(dwH, PWideChar(RT_VERSION), PWideChar(StandardKeys[ThisInfo]), 0, nil, Len);
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
Ok, that's the final version of my code: it does something but properties still seem there...
I NEED SOME HELP, please!!!...
Code: Select all
procedure TFormMain.btnChangePropsClick(Sender: TObject);
var
VersionInfo: String;
LangCharset: String;
strSubBlock: String;
InfoLength: UINT;
Len: DWORD;
Handle: DWORD;
PCharset: PLongInt;
strSourceFile: String;
dwH: dword;
begin
try
if (FileExists(Self.labedtSourceFile.Text)) then begin
strSourceFile := Self.labedtSourceFile.Text;
// Get size of version info
Len := GetFileVersionInfoSize(PChar(strSourceFile), Handle);
// Allocate VersionInfo buffer size
SetLength(VersionInfo, Len + 1);
// Get version info
if GetFileVersionInfo(PChar(strSourceFile), Handle, Len, Pointer(VersionInfo)) then begin
// Get translation info for Language / CharSet IDs
if VerQueryValue(Pointer(VersionInfo), '\VarFileInfo\Translation', Pointer(PCharset), InfoLength) then begin
LangCharset := Format('%.4x%.4x', [LoWord (PCharset^), HiWord (PCharset^)]);
// Points to location we are interested in:
strSubBlock := '\\StringFileInfo\\%04x%04x\\CompanyName';
VerQueryValue(Pointer(VersionInfo), PChar(strSubBlock), Pointer(PCharset), InfoLength);
// Modify properties:
StrCopy(PAnsiChar(PCharset), 'EDITED');
// Scrive le proprietà:
dwH := BeginUpdateResourceW(PWideChar(WideString(strSourceFile)), False);
if UpdateResourceW(dwH,
PWideChar(RT_VERSION),
PWideChar(VS_VERSION_INFO),
0,
Pointer(VersionInfo),
Len) then begin
Application.MessageBox('File properties changed succesfully!', PChar(Application.Title), 0);
EndUpdateResourceW(dwH, False);
end else begin
Application.MessageBox('Errors modifying file properties!', PChar(Application.Title), 0)
end;
end;
end;
end else begin
ShowMessage('File not exists.');
end;
except
on E:Exception do
ShowMessage(E.Message);
end;
end;
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
Update code: nothing chages but the file size (2 bytes more)
Original "CompanyName" value is read correctly, so lpBuffer correctly points to the exact memory location. Thus of course I make a mistake with the UpdateResourceW and the parameters I pass.
I have no more ideas!!!
I really need a hand!
Code: Select all
var
sz, lpHandle, tbl: Cardinal;
lpBuffer: Pointer;
strTbl: string;
int: PInteger;
hiW, loW: Word;
strSourceFile: String;
dwH: dword;
FData: Pointer;
FSize: Cardinal;
begin
try
if (FileExists(Self.labedtSourceFile.Text)) then begin
strSourceFile := Self.labedtSourceFile.Text;
// Legge le proprietà del file (struttura VersionInfo):
FSize := GETFILEVERSIONINFOSize(PChar(strSourceFile), lpHandle);
FData := AllocMem(FSize);
GETFILEVERSIONINFO(PChar(strSourceFile), lpHandle, FSize, FData);
VerQueryValue(FData, '\VarFileInfo\Translation', lpBuffer, sz);
int := lpBuffer;
hiW := HiWord(int^);
loW := LoWord(int^);
tbl := (loW shl 16) or hiW;
strTbl := Format('%x', [tbl]);
if Length(strtbl) < 8 then strTbl := '0' + strTbl;
// CompanyName:
VerQueryValue(FData, PChar('\\StringFileInfo\'+ strTbl +'\CompanyName'), lpBuffer, sz);
StrCopy(lpBuffer, 'SILVERBLACK');
dwH := BeginUpdateResourceW(PWideChar(WideString(strSourceFile)), False);
if UpdateResourceW(dwH,
PWideChar(RT_VERSION),
PWideChar(VS_VERSION_INFO),
1,
lpBuffer,
FSize) then begin
Application.MessageBox('Proprietà cambiate correttamente!', PChar(Application.Title), 0);
EndUpdateResourceW(dwH, False);
...
I have no more ideas!!!
I really need a hand!
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
Yes, but I'm still not sure about the Language parameter.madshi wrote:Does UpdateResourceW succeed?
Oh... Right!!!!!!You're giving in lpBuffer as the new version resource, that's not correct. It's the pointer to the company string, not the point to the version resource!
And so, how do I modify the resource string and, overall, pass my new string to the UpdateResourceW?
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
lpBuffer2? Somadshi wrote:Use lpBuffer2 for the string manipulation, then lpBuffer should still point to the version information block.
Code: Select all
StrCopy(lpBuffer2, 'mystringhere');
You can also check out this page:
http://www.wilsonc.demon.co.uk/delphi.htm
Colin also offers some freeware stuff about changing EXE resources. Perhaps he has some version information specific stuff built in that you can use.
http://www.wilsonc.demon.co.uk/delphi.htm
Colin also offers some freeware stuff about changing EXE resources. Perhaps he has some version information specific stuff built in that you can use.
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy
I have some experience (I'm graduating in Computer Science of my country), but knowledge is never enough and I'm always finding out that the things I don't know are soooo many!
Thanks for your help, it was appreciated. I don't want you to do the job for me, resources and low-level programming is not my main interest but I'd like to be succesful in this challenge on my own.
One last thing I don't understand (I still didn't check the article you linked) is how UpdateResourceW should be warned about lpBuffer2, because either I pass it lpBuffer or lpBuffer2, but not both!
I feel I'm near the solution...
See ya and thanks for all!
Thanks for your help, it was appreciated. I don't want you to do the job for me, resources and low-level programming is not my main interest but I'd like to be succesful in this challenge on my own.
One last thing I don't understand (I still didn't check the article you linked) is how UpdateResourceW should be warned about lpBuffer2, because either I pass it lpBuffer or lpBuffer2, but not both!
I feel I'm near the solution...
See ya and thanks for all!
You don't want to store just the company name characters into the version resource, or do you? You want to give in the whole version resource block, right? So you should give in the address of the whole version resource block. I've not fully studied your code, but it seems to me that you stored the address of the resource block in FData, so you should give that into UpdateResourceW. I think you can do the rest with lpBuffer (I guess you don't need lpBuffer2), as long as you don't give lpBuffer into UpdateResourceW.
-
- Posts: 29
- Joined: Fri Feb 17, 2006 11:47 am
- Location: Italy