Goomoo
asked on
How to change an EXE file's icon by programming?
How to change an EXE file's icon by programming?
Please give me some codes or an example.
Best regards.
Goomoo
Please give me some codes or an example.
Best regards.
Goomoo
You can do that only if the exe is currently not running. In that situation you can use BeginUpdateResourceW and related functions to change the resources of the exe. The EXE's icon is stored in the resources. If you change the icon in the resources, you'll also change the EXE's icon. BeginUpdateResourceW is only available in the NT family, it's not available in 9x. But you can use my free unit "madRes" (part of the free package "madBasic"), which makes BeginUpdateResourceW available in 9x, too.
Sorry, can't give you code, have no time for that.
www.madshi.net
Sorry, can't give you code, have no time for that.
www.madshi.net
What exactly are you trying to do...
Are you wanting to write a delphi app that can change the icons in other delphi apps? or any other apps?
Or perhaps you want a delphi program that can change its own icon?
Are you creating a general utility to let others change the icons in whatever exe files they like?
Or do you just need to USE a utility that can change other exe's icons? if so try ResHack.exe .. it is a nice freeware delphi app that can work with the resources of an exe file... you can change icons easily using this tool.
If you want to add code to your own programs to let them alter the icons of other executables then madshi's code is just what you need... I don't think it can change the icon of an exe that has been been compressed along with its resources.... to do that you will need to add de-compression code for all of the commercial and freeware compressors... a big task! or just tell your users that the exe must be uncompressed or the icons cannot be changed.
Are you wanting to write a delphi app that can change the icons in other delphi apps? or any other apps?
Or perhaps you want a delphi program that can change its own icon?
Are you creating a general utility to let others change the icons in whatever exe files they like?
Or do you just need to USE a utility that can change other exe's icons? if so try ResHack.exe .. it is a nice freeware delphi app that can work with the resources of an exe file... you can change icons easily using this tool.
If you want to add code to your own programs to let them alter the icons of other executables then madshi's code is just what you need... I don't think it can change the icon of an exe that has been been compressed along with its resources.... to do that you will need to add de-compression code for all of the commercial and freeware compressors... a big task! or just tell your users that the exe must be uncompressed or the icons cannot be changed.
ASKER
Thank you, Madshi.
Thank you, Gwena.
I want to change a Delphi app's icon. The exe-file has been compressed by UPX. I have changed the exe-file's icon by ExeScope successfully, But I hope I can change the file's icon by codes.
or
Who can show me an example,how to change a non-compressed exe-file's icon?
Thank you, Gwena.
I want to change a Delphi app's icon. The exe-file has been compressed by UPX. I have changed the exe-file's icon by ExeScope successfully, But I hope I can change the file's icon by codes.
or
Who can show me an example,how to change a non-compressed exe-file's icon?
Using my unit madRes it's fairly easy:
- BeginUpdateResourceW (exe file path)
- LoadIconGroupResourceW (new ico file path)
- EndUpdateResourceW
That's it. Just give in the correct parameters. Must be wide strings. See here for documentation:
http://help.madshi.net/madResUnit.htm
Here's a direct download:
http://madshi.bei.t-online.de/madCollectionBeta.exe
Regards, Madshi.
- BeginUpdateResourceW (exe file path)
- LoadIconGroupResourceW (new ico file path)
- EndUpdateResourceW
That's it. Just give in the correct parameters. Must be wide strings. See here for documentation:
http://help.madshi.net/madResUnit.htm
Here's a direct download:
http://madshi.bei.t-online.de/madCollectionBeta.exe
Regards, Madshi.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Overwriting the sectors won't help here, because depending on which color depths and resolutions the old and the new icon supports, the resource section can grow or get smaller.
P.S: UPX is nice, but it has one problem: It changes the addresses of all functions. As a result my exception tracker "madExcept" doesn't work with UPX compressed exes. Petite and AsPack don't change the addresses of the functions.
Yup... you have to pad out the exe so that the original has room to be grown. When I used to modify exe files directly at the sector level I would add a bunch of stuff to the end so I had room to spare...then check to see which bytes of my modified copy were different from the original and insert every changed byte into the sectors holding the original.... the exes never minded that a bunch of padding was left at the end... but it is a bit of a kludge... actually the whole idea of modifying an exe directly on the disk is risky... that's where the praying comes in handy :-)
I understand about the differing icon types and sizes.. I made an exe that could change its icon directly using exemod... but it only worked with icons of the exact same size/type... I suppose that is worth something if you were to originally use a large icon and somehow convert any new one a user chose into the same type before you inserted it.
Thanks for the info about UPX,AsPack and Petite... that's good stuff to know :-)
I understand about the differing icon types and sizes.. I made an exe that could change its icon directly using exemod... but it only worked with icons of the exact same size/type... I suppose that is worth something if you were to originally use a large icon and somehow convert any new one a user chose into the same type before you inserted it.
Thanks for the info about UPX,AsPack and Petite... that's good stuff to know :-)
{
Copyright 2003-2004 by Sima Huapeng
smhp@163.net
}
unit Pak;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, shellApi;
type
TexePak = class(TComponent)
private
fSourceFile: string;
fDestFile: string;
fOutFile: String;
procedure SetSourceFile(const Value: string);
procedure SetDestFile(const Value: string);
procedure SetOutFile(const Value: string);
protected
public
constructor Create(AOwner: TComponent); reintroduce;
destructor Destroy; override;
function ExchangeExeIcon:Boolean;
property SourceFile: string read fSourceFile write SetSourceFile;
property DestFile: string read fDestFile write SetDestFile;
property OutFile: string read fOutFile write SetOutFile;
published
end;
implementation
constructor TexePak.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TexePak.Destroy;
begin
inherited;
end;
function TexePak.ExchangeExeIcon(): Boolean;
const
readlen=10; //每次读 取&# 23383;! 410;ਤ 8;, 可&# 25913; 464;
icolen=766; //32*32图标 8271;ò 30;,੬ 1;据 研 究前126为 ; 图标头,& #21518;640 为&# 22270; 标数据
var
i,j,itemp,nPos:int64; // nPos为目௚ 0;图 标&# 22312; 446;௚ 0;文 件的位&# 32622;
ci,cj:array[0..readlen-1] of char;
bOK:boolean;
SourceIcon,DestIcon:TIcon;
SIconStream,s,sDest:TMemor yStream;
begin
Result:=False;
bOK:=false;
if ExtractIcon(0,PChar(fSourc eFile),UIN T(-1))=0 then exit;
SourceIcon:=TIcon.Create;
try
try
SourceIcon.Handle:=Extract Icon(0,PCh ar(fSource File),0); //选择第 一&# 20010; 270;੧ 1;
if ExtractIcon(0,PChar(fDestF ile),UINT( -1))=0 then exit;
DestIcon:=TIcon.Create;
try
DestIcon.Handle:=ExtractIc on(0,PChar (fDestFile ),0);// 6873;ý 21;第 ;一& #20010; 2270;Ċ 31;
SIconStream:=TMemoryStream .Create;
try
DestIcon.SaveToStream(sIco nStream);
SDest:=TMemoryStream.Creat e;
try
sDest.LoadFromFile(fDestFi le);
i:=0;j:=0; //以下程 序&# 26597; 214; 目的图&# 26631; 312;௤ 6;的 程&# 24207; 中的位&# 32622;
while i<sDest.size do
begin
itemp:=i;
j:=126;
ci:='';cj:='';
while (String(ci)=String(cj)) and (i<SDest.size) and (j<icolen) do
begin
i:=i+readlen;
j:=j+readlen;
SDest.Position:=i;
SDest.read(ci,readlen);
SiconStream.Position:=j;
SiconStream.Read(cj,readle n);
end;
if j<icolen then
i:=itemp+1 //没找到
else
begin
nPos:=itemp; //找到
bOK:=true;
break;
end;
end;
if bOK=false then exit;//目标 5991;Ê 14;二 ;进& #21046; 码中未&# 25214; 040;ࢳ 0;标
SIconStream.Clear;//ळ 8;源 程&# 24207; 270;੧ 1;存 入
SourceIcon.SaveToStream(SI conStream) ;
SIconStream.position:=126;
s:=TMemoryStream.Create;
try
sDest.Position:=0;
s.CopyFrom(sDest,nPos);//& #23558; 0446;į 40;程 ;序& #22270; 6631;Ò 69;数 ;据& #25335; 0837;
s.CopyFrom(SIconStream,640 ); //将源程 序&# 22270; 631;৥ 5;入
if sDest.size>sDest.Position+ 640 then //将目的 程&# 24207; 097;߯ 3;数 据&# 25335; 837;
begin
sDest.Position:=sDest.Posi tion+640;
s.CopyFrom(sDest,sDest.Siz e-sDest.Po sition);
end;
s.SaveToFile(fOutFile); //改造好 的&# 31243; 207;ढ 4; 放在OutFile 5991;Ê 14;中 ;
finally
S.Free;
end;
finally
sDest.Free;
end;
finally
SIconStream.Free;
end;
finally
DestIcon.Free;
end;
finally
SourceIcon.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
procedure TexePak.SetDestFile(const Value: string);
begin
fDestFile := value;
end;
procedure TexePak.SetOutFile(const Value: string);
begin
fOutFile := Value;
end;
procedure TexePak.SetSourceFile(cons t Value: string);
begin
fSourceFile := Value;
end;
end.
Copyright 2003-2004 by Sima Huapeng
smhp@163.net
}
unit Pak;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, shellApi;
type
TexePak = class(TComponent)
private
fSourceFile: string;
fDestFile: string;
fOutFile: String;
procedure SetSourceFile(const Value: string);
procedure SetDestFile(const Value: string);
procedure SetOutFile(const Value: string);
protected
public
constructor Create(AOwner: TComponent); reintroduce;
destructor Destroy; override;
function ExchangeExeIcon:Boolean;
property SourceFile: string read fSourceFile write SetSourceFile;
property DestFile: string read fDestFile write SetDestFile;
property OutFile: string read fOutFile write SetOutFile;
published
end;
implementation
constructor TexePak.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TexePak.Destroy;
begin
inherited;
end;
function TexePak.ExchangeExeIcon():
const
readlen=10; //每次读
icolen=766; //32*32图标
var
i,j,itemp,nPos:int64; // nPos为目௚
ci,cj:array[0..readlen-1] of char;
bOK:boolean;
SourceIcon,DestIcon:TIcon;
SIconStream,s,sDest:TMemor
begin
Result:=False;
bOK:=false;
if ExtractIcon(0,PChar(fSourc
SourceIcon:=TIcon.Create;
try
try
SourceIcon.Handle:=Extract
if ExtractIcon(0,PChar(fDestF
DestIcon:=TIcon.Create;
try
DestIcon.Handle:=ExtractIc
SIconStream:=TMemoryStream
try
DestIcon.SaveToStream(sIco
SDest:=TMemoryStream.Creat
try
sDest.LoadFromFile(fDestFi
i:=0;j:=0; //以下程
while i<sDest.size do
begin
itemp:=i;
j:=126;
ci:='';cj:='';
while (String(ci)=String(cj)) and (i<SDest.size) and (j<icolen) do
begin
i:=i+readlen;
j:=j+readlen;
SDest.Position:=i;
SDest.read(ci,readlen);
SiconStream.Position:=j;
SiconStream.Read(cj,readle
end;
if j<icolen then
i:=itemp+1 //没找到
else
begin
nPos:=itemp; //找到
bOK:=true;
break;
end;
end;
if bOK=false then exit;//目标
SIconStream.Clear;//ळ
SourceIcon.SaveToStream(SI
SIconStream.position:=126;
s:=TMemoryStream.Create;
try
sDest.Position:=0;
s.CopyFrom(sDest,nPos);//&
s.CopyFrom(SIconStream,640
if sDest.size>sDest.Position+
begin
sDest.Position:=sDest.Posi
s.CopyFrom(sDest,sDest.Siz
end;
s.SaveToFile(fOutFile); //改造好
finally
S.Free;
end;
finally
sDest.Free;
end;
finally
SIconStream.Free;
end;
finally
DestIcon.Free;
end;
finally
SourceIcon.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
procedure TexePak.SetDestFile(const Value: string);
begin
fDestFile := value;
end;
procedure TexePak.SetOutFile(const Value: string);
begin
fOutFile := Value;
end;
procedure TexePak.SetSourceFile(cons
begin
fSourceFile := Value;
end;
end.
Interesting code
But why icon size 766 ?
Is this the size of an 16*16 Icon with 16 colors?
Is it possible to do this also for 32 bit or 256 color icons?
If this approach works for those icons I d like to ask this question in an own thread
But why icon size 766 ?
Is this the size of an 16*16 Icon with 16 colors?
Is it possible to do this also for 32 bit or 256 color icons?
If this approach works for those icons I d like to ask this question in an own thread
erm just use madshi's source works brill used it my self with my installer,
which madshi isnt quite finished yet :D
that code u have wrote out only acumpesses for one icon type how ever xp suports
32bit alpha channel icons and also they can be any size not just 16x16 or 32x32 but stuff like 512x512
which madshi isnt quite finished yet :D
that code u have wrote out only acumpesses for one icon type how ever xp suports
32bit alpha channel icons and also they can be any size not just 16x16 or 32x32 but stuff like 512x512
my msn:end_sub@hotmail.com
here a class for modifing icon from win2000 or later.
~~~~~~~~~~~
unit IconModifyUnit;
interface
uses Windows, SysUtils, Classes ;
type
TIconModifier = Class(TComponent)
private
FSourceFile : String ;
FDestFile : String ;
procedure SetSourceFile(AFile: String) ;
procedure SetDestFile(AFile: String) ;
function ModifyIconForNt(SourceInde x, DestIndex: Cardinal = 1): Boolean ;
function ModifyIconFor9x(SourceInde x, DestIndex: Cardinal = 1): Boolean ;
public
property SourceFile: String Read FSourceFile Write SetSourceFile ;
property DestFile : String Read FDestFile Write SetDestFile ;
function ModifyIcon(SourceIndex, DestIndex: Cardinal = 1): Boolean ;
end;
implementation
procedure TIconModifier.SetSourceFil e(AFile: String);
begin
FSourceFile := AFile ;
end;
procedure TIconModifier.SetDestFile( AFile: String);
begin
FDestFile := AFile ;
end;
function TIconModifier.ModifyIconFo rNt(Source Index, DestIndex: Cardinal = 1): Boolean ;
var
hModule : Cardinal ;
hResFind : Cardinal ;
hResLoad : Cardinal ;
pResLock : PChar ;
hResUpdate: Cardinal ;
begin
Result := false ;
hModule := LoadLibrary(PChar(FSourceF ile));
if hModule = 0 then
Exit ;
try
hResFind := FindResource(hModule, MakeIntResource(SourceInde x+1), RT_ICON) ;
if hResFind = 0 then
Exit ;
hResLoad := LoadResource(hModule, hResFind) ;
if hResLoad = 0 then
Exit ;
pResLock := LockResource(hResLoad) ;
if pResLock = nil then
Exit ;
hResUpdate := BeginUpdateResource(PChar( FDestFile) , false) ;
if hResUpdate = 0 then
Exit ;
if not UpdateResource(hResUpdate,
RT_ICON,
MakeIntResource(DestIndex + 1),
0, //local language
pResLock,
SizeofResource(hModule, hResFind)) then
Exit ;
if not EndUpdateResource(hResUpda te, false) then
Exit ;
finally
FreeLibrary(hModule) ;
end;
Result := true ;
end;
function TIconModifier.ModifyIconFo r9x(Source Index, DestIndex: Cardinal = 1): Boolean ;
begin
Result := false ;
end;
function TIconModifier.ModifyIcon(S ourceIndex , DestIndex: Cardinal = 1): Boolean ;
begin
Result := false ;
if Win32PlatForm = VER_PLATFORM_WIN32_NT then
Result := ModifyIconForNt(SourceInde x, DestIndex)
else
Result := ModifyIconFor9x(SourceInde x, DestIndex) ; // not implement now.
end;
end.
example :
use IconModifyUnit ;
procedure TForm1.Button1Click(Sender : TObject);
var
im : TIconModifier ;
source, dest: String ;
begin
if OpenDialog1.Execute then
source := OpenDialog1.FileName
else
Exit ;
if OpenDialog2.Execute then
dest := OpenDialog2.FileName
else
Exit ;
im := TIconModifier.Create(Self) ;
im.SourceFile := source ; //a file includes source icon(s), exe or dll format.
im.DestFile := dest ; //file includes icon which will be modified. exe or dll.
if im.ModifyIcon(1) then
MessageBox(Handle,'success ful.', 'info', MB_OK + MB_ICONINFORMATION)
else
MessageBox(Handle,'fail.', 'info', MB_OK + MB_ICONINFORMATION) ;
im.Free ;
end.
08 13, 2004
Regards, adayuer
~~~~~~~~~~~
unit IconModifyUnit;
interface
uses Windows, SysUtils, Classes ;
type
TIconModifier = Class(TComponent)
private
FSourceFile : String ;
FDestFile : String ;
procedure SetSourceFile(AFile: String) ;
procedure SetDestFile(AFile: String) ;
function ModifyIconForNt(SourceInde
function ModifyIconFor9x(SourceInde
public
property SourceFile: String Read FSourceFile Write SetSourceFile ;
property DestFile : String Read FDestFile Write SetDestFile ;
function ModifyIcon(SourceIndex, DestIndex: Cardinal = 1): Boolean ;
end;
implementation
procedure TIconModifier.SetSourceFil
begin
FSourceFile := AFile ;
end;
procedure TIconModifier.SetDestFile(
begin
FDestFile := AFile ;
end;
function TIconModifier.ModifyIconFo
var
hModule : Cardinal ;
hResFind : Cardinal ;
hResLoad : Cardinal ;
pResLock : PChar ;
hResUpdate: Cardinal ;
begin
Result := false ;
hModule := LoadLibrary(PChar(FSourceF
if hModule = 0 then
Exit ;
try
hResFind := FindResource(hModule, MakeIntResource(SourceInde
if hResFind = 0 then
Exit ;
hResLoad := LoadResource(hModule, hResFind) ;
if hResLoad = 0 then
Exit ;
pResLock := LockResource(hResLoad) ;
if pResLock = nil then
Exit ;
hResUpdate := BeginUpdateResource(PChar(
if hResUpdate = 0 then
Exit ;
if not UpdateResource(hResUpdate,
RT_ICON,
MakeIntResource(DestIndex + 1),
0, //local language
pResLock,
SizeofResource(hModule, hResFind)) then
Exit ;
if not EndUpdateResource(hResUpda
Exit ;
finally
FreeLibrary(hModule) ;
end;
Result := true ;
end;
function TIconModifier.ModifyIconFo
begin
Result := false ;
end;
function TIconModifier.ModifyIcon(S
begin
Result := false ;
if Win32PlatForm = VER_PLATFORM_WIN32_NT then
Result := ModifyIconForNt(SourceInde
else
Result := ModifyIconFor9x(SourceInde
end;
end.
example :
use IconModifyUnit ;
procedure TForm1.Button1Click(Sender
var
im : TIconModifier ;
source, dest: String ;
begin
if OpenDialog1.Execute then
source := OpenDialog1.FileName
else
Exit ;
if OpenDialog2.Execute then
dest := OpenDialog2.FileName
else
Exit ;
im := TIconModifier.Create(Self)
im.SourceFile := source ; //a file includes source icon(s), exe or dll format.
im.DestFile := dest ; //file includes icon which will be modified. exe or dll.
if im.ModifyIcon(1) then
MessageBox(Handle,'success
else
MessageBox(Handle,'fail.',
im.Free ;
end.
08 13, 2004
Regards, adayuer
Thanks a lot.
Can file no 1 be an icon itself or must it be an exe or dll?
Thanks anyway
cheers
hh
Can file no 1 be an icon itself or must it be an exe or dll?
Thanks anyway
cheers
hh
win32 app (exe) usually has ONE icon at least, the icon's index from 1 to all Icons count, but sometimes, if app has a icongroup,more than one icon in the icongroup, the icon's index is hard to get.
my msn : adayuer@msn.com
my msn : adayuer@msn.com
ASKER