我知道nt下有这样的api但是98不支持。我想请教别的方法,比如自己分析pe文件格式。如果哪位知道pe格式那篇大家众所周知的文章,请不必给我url了,请给我详细解释一下,
我会一点汇编,具体怎样更改,或者哪里是图标部分分不够再加!!谢谢!

解决方案 »

  1.   

    unit UnitOK;//用Delphi编程替代EXE文件图标,在Delphi6+win98调试通过,如果有BUG请诉我!interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls,shellapi;type
      TForm1 = class(TForm)
        Label1: TLabel;
        Edit1: TEdit;
        Label2: TLabel;
        Edit2: TEdit;
        Button1: TButton;
        Button2: TButton;
        OpenDialog1: TOpenDialog;
        OpenDialog2: TOpenDialog;
        StatusBar1: TStatusBar;
        procedure Button2Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button2Click(Sender: TObject);
    begin
        Close;
    end;procedure TForm1.Button1Click(Sender: TObject);
    const
            readlen=10;  //每次读取字节数,可改变
            icolen=766;//32*32图标长度,根据研究前126为图标头,后640为图标数据
    var
            i,j,itemp,nPos:int64;// nPos为目的图标在目的文件的位置
            ci,cj:array[0..readlen-1] of char;
            SourceFile,DestFile:String;//如果要把记事本图标换成瑞星杀毒软件图标
            bOK:boolean;//则SourceFile='C:\windows\notepad.exe',DestFile:='C:\Progra
    m Files\rising\rav\ravmon.exe'
            SourceIcon,DestIcon:TIcon;
            SIconStream,s,sDest:TMemoryStream;
    begin
            bOK:=false;
            if OpenDialog1.Execute then
                SourceFile:=OpenDialog1.FileName
            else
                exit;
            if  AnsiUpperCase(ExtractFileExt(SourceFile))<>'.EXE' then
            begin
                ShowMessage(AnsiUpperCase(ExtractFileExt(SourceFile)));
                exit;
            end;
            Edit1.Text:=SourceFile;
            if OpenDialog2.Execute then
                DestFile:=OpenDialog2.FileName
            else
                exit;
            if  AnsiUpperCase(ExtractFileExt(DestFile))<>'.EXE' then
                exit;
            Edit2.Text:=DestFile;
            SourceIcon:=TIcon.Create;
            case ExtractIcon(handle,PChar(SourceFile),UINT(-1)) of
                0:begin ShowMessage('源程序没有图标');exit;end;
                1:;
                else ShowMessage('源程序有多个图标,本程序选择第一个图标');
            end;
            SourceIcon.Handle:=ExtractIcon(handle,PChar(SourceFile),0);//选择第一个图

            DestIcon:=TIcon.Create;//选择第N个图标为 ExtractIcon(handle,PChar(Source
    File),N-1)
            case ExtractIcon(handle,PChar(DestFile),UINT(-1)) of
                0:begin ShowMessage('目的程序没有图标');exit;end;
                1:;
                else ShowMessage('目的程序有多个图标,本程序选择第一个图标替换');
            end;
            DestIcon.Handle:=ExtractIcon(handle,PChar(DestFile),0);//选择第一个图标
            SIconStream:=TMemoryStream.Create;
            DestIcon.SaveToStream(sIconStream);
            if sIconStream.size<>icolen then
                ShowMessage('SIcon.size<>icolen');
            SDest:=TMemoryStream.Create;
            sDest.LoadFromFile(DestFile);
            i:=0;j:=0;   //以下程序查找目的图标在目的程序中的位置
            while  i< sDest.size do
            begin
                   itemp:=i;
                   j:=126;
    {               repeat
                        SDest.Position:=i;
                        sDest.read(ci,Readlen);
                        SiconStream.Position:=j;
                        SIconStream.Read(cj,Readlen);
                        i:=i+Readlen;
                        j:=j+Readlen;
                   until (String(ci)=String(cj)) and (i<sDest.size) and (j<icolen);
    }                       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,readlen);
                            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(SIconStream);        SIconStream.position:=126;
            s:=TMemoryStream.Create;        sDest.Position:=0;
            s.CopyFrom(sDest,nPos);//将目的程序图标前数据拷入
            s.CopyFrom(SIconStream,640); //将源程序图标拷入
            if sDest.size>sDest.Position+640 then //将目的程序剩余数据拷入
            begin
                 sDest.Position:=sDest.Position+640;
                 s.CopyFrom(sDest,sDest.Size-sDest.Position);
            end;
            s.SaveToFile(Extractfilepath(application.exename)+'Result.exe');
            SourceIcon.Free;DestIcon.Free; //改造好的程序存放在本目录Result.exe文件中
            SIconStream.Free;s.Free;sDest.Free;
            ShowMessage(Extractfilepath(application.exename)+'Result.exe');
    end;
    //以上程序可以将目的程序的第一个图标换成源程序的第一个图标,经实证很多程序有二个
    //或更多图标,转换原理相似,不在陈述
    end.
      

  2.   

    unit UnitOK;//用Delphi编程替代EXE文件图标,在Delphi6+win98调试通过,如果有BUG请诉我!interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, ComCtrls,shellapi;type
      TForm1 = class(TForm)
        Label1: TLabel;
        Edit1: TEdit;
        Label2: TLabel;
        Edit2: TEdit;
        Button1: TButton;
        Button2: TButton;
        OpenDialog1: TOpenDialog;
        OpenDialog2: TOpenDialog;
        StatusBar1: TStatusBar;
        procedure Button2Click(Sender: TObject);
        procedure Button1Click(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button2Click(Sender: TObject);
    begin
        Close;
    end;procedure TForm1.Button1Click(Sender: TObject);
    const
            readlen=10;  //每次读取字节数,可改变
            icolen=766;//32*32图标长度,根据研究前126为图标头,后640为图标数据
    var
            i,j,itemp,nPos:int64;// nPos为目的图标在目的文件的位置
            ci,cj:array[0..readlen-1] of char;
            SourceFile,DestFile:String;//如果要把记事本图标换成瑞星杀毒软件图标
            bOK:boolean;//则SourceFile='C:\windows\notepad.exe',DestFile:='C:\Progra
    m Files\rising\rav\ravmon.exe'
            SourceIcon,DestIcon:TIcon;
            SIconStream,s,sDest:TMemoryStream;
    begin
            bOK:=false;
            if OpenDialog1.Execute then
                SourceFile:=OpenDialog1.FileName
            else
                exit;
            if  AnsiUpperCase(ExtractFileExt(SourceFile))<>'.EXE' then
            begin
                ShowMessage(AnsiUpperCase(ExtractFileExt(SourceFile)));
                exit;
            end;
            Edit1.Text:=SourceFile;
            if OpenDialog2.Execute then
                DestFile:=OpenDialog2.FileName
            else
                exit;
            if  AnsiUpperCase(ExtractFileExt(DestFile))<>'.EXE' then
                exit;
            Edit2.Text:=DestFile;
            SourceIcon:=TIcon.Create;
            case ExtractIcon(handle,PChar(SourceFile),UINT(-1)) of
                0:begin ShowMessage('源程序没有图标');exit;end;
                1:;
                else ShowMessage('源程序有多个图标,本程序选择第一个图标');
            end;
            SourceIcon.Handle:=ExtractIcon(handle,PChar(SourceFile),0);//选择第一个图

            DestIcon:=TIcon.Create;//选择第N个图标为 ExtractIcon(handle,PChar(Source
    File),N-1)
            case ExtractIcon(handle,PChar(DestFile),UINT(-1)) of
                0:begin ShowMessage('目的程序没有图标');exit;end;
                1:;
                else ShowMessage('目的程序有多个图标,本程序选择第一个图标替换');
            end;
            DestIcon.Handle:=ExtractIcon(handle,PChar(DestFile),0);//选择第一个图标
            SIconStream:=TMemoryStream.Create;
            DestIcon.SaveToStream(sIconStream);
            if sIconStream.size<>icolen then
                ShowMessage('SIcon.size<>icolen');
            SDest:=TMemoryStream.Create;
            sDest.LoadFromFile(DestFile);
            i:=0;j:=0;   //以下程序查找目的图标在目的程序中的位置
            while  i< sDest.size do
            begin
                   itemp:=i;
                   j:=126;
    {               repeat
                        SDest.Position:=i;
                        sDest.read(ci,Readlen);
                        SiconStream.Position:=j;
                        SIconStream.Read(cj,Readlen);
                        i:=i+Readlen;
                        j:=j+Readlen;
                   until (String(ci)=String(cj)) and (i<sDest.size) and (j<icolen);
    }                       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,readlen);
                            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(SIconStream);        SIconStream.position:=126;
            s:=TMemoryStream.Create;        sDest.Position:=0;
            s.CopyFrom(sDest,nPos);//将目的程序图标前数据拷入
            s.CopyFrom(SIconStream,640); //将源程序图标拷入
            if sDest.size>sDest.Position+640 then //将目的程序剩余数据拷入
            begin
                 sDest.Position:=sDest.Position+640;
                 s.CopyFrom(sDest,sDest.Size-sDest.Position);
            end;
            s.SaveToFile(Extractfilepath(application.exename)+'Result.exe');
            SourceIcon.Free;DestIcon.Free; //改造好的程序存放在本目录Result.exe文件中
            SIconStream.Free;s.Free;sDest.Free;
            ShowMessage(Extractfilepath(application.exename)+'Result.exe');
    end;
    //以上程序可以将目的程序的第一个图标换成源程序的第一个图标,经实证很多程序有二个
    //或更多图标,转换原理相似,不在陈述
    end.
      

  3.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
    fs:tfilestream;
    icnss,appss:tstringstream;
    appicn:ticon;
    icnhandle:hicon;
    ipos:integer;
    begin
      //创建自身文件流对象:
      fs:=tfilestream.Create(application.ExeName,fmopenread+fmsharedenynone);
      fs.Position:=0;
      //创建自身文件字符串流:
      appss:=tstringstream.Create('');
      appss.Position:=0;
      appss.CopyFrom(fs,0);
      fs.Free;
      //创建自身图标对象:
      appicn:=ticon.Create;
      icnhandle:=extracticon(handle,pchar(application.exename),0);
      appicn.Handle:=icnhandle;
      //创建自身图标字符串流对象:
      icnss:=tstringstream.Create('');
      appicn.SaveToStream(icnss);
      appicn.Free;
      //查找真图标内容在自身exe中的位置:
      ipos:=pos(icnss.DataString,appss.DataString);
      //奇怪的是,总是显示 0 。
      showmessage(inttostr(ipos));
      appss.Free;
      icnss.Free;end;
      

  4.   

    我确保icnhandle不是0,并且icnss.size=766,appss.size<>0
      

  5.   

    寄给你的信退回。就在这留言了:
      delphi资源和别的程序不同,如可以用第三方工具修改,可以试试EXESCOPE,或到http://www.hanzify.org/找找相关的工具(专门修改delphi资源的)
      

  6.   

    来信收到。寄给你的信退回。就在这留言了:
      delphi资源和别的程序不同,如可以用第三方工具修改,可以试试EXESCOPE,或到http://www.hanzify.org/找找相关的工具(专门修改delphi资源的)
      

  7.   

    我想无论delphi也好,vc也好,都是遵循pe文件格式编译文件的,我只求更改文件显示在“我的电脑”里面的图标,别的不用,是不是就必须分析pe文件格式?或者说exescope怎么做的?我用dede烦编译过exescope,它就是delphi作的。
      

  8.   

    >>ipos:=pos(icnss.DataString,appss.DataString);
    >>  //奇怪的是,总是显示 0 。我编过一个测试程序,在应用程序中找不到完整的图标数据,所以pos(icnss.DataString,appss.DataString)总是显示 0 ,但是图标的后640
    字节可以在应用程序中找到,而且该程序可以成功修改图标,但具体前126个字节的结构我也不大清楚请高手剔教
      

  9.   

    >>我只求更改文件显示在“我的电脑”里面的图标,别的不用,是不是就必须分析>>pe文件格式?
    我用的是可以WIN98,可以成功修改可执行文件显示在“我的电脑”里面的图标
      

  10.   

    function ChangeAppIcon(AppFile,IconFile:string;Index:integer=0):boolean;
    var
    ms,newicn:tmemorystream;
    oldicn,appss,appicnss:tstringstream;
    appicn:ticon;
    i,j,icnlen,icnfsize,icnhdlen:integer;
    icnhd:hicon;
    fs,icnfs:tfilestream;
    begin
    result:=false;
    icnhdlen:=126;
    if (not fileexists(appfile)) or (not fileexists(iconfile)) then exit;
    try   fs:=tfilestream.Create(appfile,fmopenreadwrite+fmsharedenywrite);
       appss:=tstringstream.Create('');
       appss.Position:=0;
       fs.Position:=0;
       appss.CopyFrom(fs,0);
       //////////
       appicn:=ticon.Create;
       icnhd:=extracticon(application.Handle,pchar(appfile),index);
       if icnhd<=1 then
       begin
         raise exception.Create('No such an icon index '+inttostr(index)+' in file: "'+appfile+' ".');
       end;
       appicn.Handle:=icnhd;
       appicnss:=tstringstream.Create('');
       appicn.SaveToStream(appicnss);
       appicn.Free;
       appicn:=nil;
       icnlen:=appicnss.Size-icnhdlen;
       //////////
       appicnss.Position:=icnhdlen;
       oldicn:=tstringstream.Create('');
       oldicn.Position:=0;
       appicnss.Position:=icnhdlen;
       oldicn.CopyFrom(appicnss,icnlen);
       appicnss.Free;
       //////////
       i:=pos(oldicn.DataString,appss.DataString);
       appss.Free;
       appss:=nil;
       oldicn.Free;
       ///////////
       icnfs:=tfilestream.Create(iconfile,fmopenread+fmsharedenynone);
       newicn:=tmemorystream.Create;
       icnfs.Position:=icnhdlen;
       newicn.Position:=0;
       newicn.CopyFrom(icnfs,icnfs.Size-icnhdlen);
       icnfs.Free;
    /////////////////
       if i<=0 then
       begin
         raise exception.Create('Cannot find icon data in file: "'+appfile+' ".');
       end;
       if icnlen<>newicn.Size then
       begin
        ms:=tmemorystream.Create;
         fs.Position:=i+icnlen-1;
         ms.Position:=0;
         ms.CopyFrom(fs,fs.Size-fs.Position);
         fs.Position:=i-1;
         newicn.Position:=0;
         fs.CopyFrom(newicn,0);
         ms.Position:=0;
         fs.CopyFrom(ms,0);
         fs.Position:=0;
         fs.Size:=i+icnlen-1+ms.Size;
         ms.Free;
       end
       else
       begin
         fs.Position:=i-1;
         newicn.Position:=0;
         fs.CopyFrom(newicn,0);
       end;
       newicn.Free;
       /////////////////
       result:=true;
    finally
      fs.Free;
    end;
    end;
      

  11.   

    \delphi6\Borland\Delphi6\Demos\ResXplor有这样的一个例子啊,可是看一下我可看不懂!
      

  12.   

    最不讲究注释的就是delphi的demos!!!!
    真让人费解!
      

  13.   

    同意1212() :
    可以试试EXESCOPE下载一个ExeScope,随便捣鼓一下就知道怎么做了,不需要教程。
      

  14.   

    implementation{$R *.dfm}//符号'>>'表示该行已被修改,以下代码在WIN98+DELPHI6.0下调试通过
    function ChangeAppIcon(AppFile,IconFile,NewAppFile:string;Index:integer=0):boolean;
    var     //>>增加NewAppFile,用于保存修改图标后应用程序
    ms,newicn:tmemorystream;
    oldicn,appss,appicnss:tstringstream;
    appicn:ticon;
    i,j,icnlen,icnfsize,icnhdlen:integer;
    icnhd:hicon;
    fs,icnfs,newapp:tfilestream;//>>newapp,用于保存新应用程序的数据流
    begin
    result:=false;
    icnhdlen:=126;
    if (not fileexists(appfile)) or (not fileexists(iconfile)) then exit;
    try   fs:=tfilestream.Create(appfile,fmOpenRead or fmsharedenywrite);//>>经测试,appfile以
       appss:=tstringstream.Create('');//fmopenreadwrite方式打开后执行extracticon(application.Handle,    //pchar(appfile),index)会报错,所以改为fmOpenRead,修改图标后应用程序保存在NewAppFile;
       //至于报错原因我也不知道,欢迎高手指点.如果你不喜欢生成新应用程序的话,建议你,先提取图标,后打开
       //应用程序就可以了(即,先执行extracticon,再执行tfilestream.Create(appfile.....)
       appss.Position:=0;
       fs.Position:=0;
       appss.CopyFrom(fs,0);
       appicn:=ticon.Create;
       icnhd:=extracticon(applicaion.Handle,pchar(appfile),index);
       if icnhd<=1 then//正常应用<1  
       begin
         raise exception.Create('No such an icon index '+inttostr(index)+inttostr(icnhd)+' in file: "'+appfile+' ".');
       end;
     //  form1.Image1.Picture.Icon.Handle :=icnhd;调试用,可删去
     //  form1.Image1.Refresh;
       appicn.Handle:=icnhd;
       appicnss:=tstringstream.Create('');
       appicn.SaveToStream(appicnss);
       appicn.Free;
       appicn:=nil;
       icnlen:=appicnss.Size-icnhdlen;
       Form1.Edit1.text:=inttostr(icnlen);///////
       //////////
       appicnss.Position:=icnhdlen;
       oldicn:=tstringstream.Create('');
       oldicn.Position:=0;
       appicnss.Position:=icnhdlen;
       oldicn.CopyFrom(appicnss,icnlen);
       form1.Edit2.Text:=inttostr(oldicn.Size);
       appicnss.Free;
       //////////
       i:=pos(oldicn.DataString,appss.DataString);
       appss.Free;
       appss:=nil;
       oldicn.Free;
       form1.edit3.text:=inttostr(i);
       ///////////
       icnfs:=tfilestream.Create(iconfile,fmopenread+fmsharedenynone);
       newicn:=tmemorystream.Create;
       icnfs.Position:=icnhdlen;
       newicn.Position:=0;
       newicn.CopyFrom(icnfs,icnfs.Size-icnhdlen);
       icnfs.Free;
    /////////////////
       if i<=0 then
       begin
         raise exception.Create('Cannot find icon data in file: "'+appfile+' ".');
       end;
       if icnlen<>newicn.Size then
       begin  //if icnlen<>newicn.Size then exit;
         Showmessage('icnlen:='+inttostr(icnlen)+'<>'+'newicn.Size'+inttostr(newicn.Size ));
         ms:=tmemorystream.Create;
         fs.Position:=i+icnlen-1;
         ms.Position:=0;
         ms.CopyFrom(fs,fs.Size-fs.Position);
         fs.Position:=i-1;
         newicn.Position:=0;
         fs.CopyFrom(newicn,0);
         ms.Position:=0;
         fs.CopyFrom(ms,0);
         fs.Position:=0;
         fs.Size:=i+icnlen-1+ms.Size;
         ms.Free;
       end
       else
       begin
    //    showmessage('icnlen=newicn.size');
        newapp:=tfilestream.Create(newappfile,fmCreate);//<<
        newapp.CopyFrom(fs,0);//<<
        newapp.Position:=i-1;//<<
        newicn.Position:=0;//<<
        newapp.CopyFrom(newicn,640);//<<
        newapp.Free;//<<
    {    fs.Position:=i-1;
         newicn.Position:=0;
         fs.CopyFrom(newicn,0);}   end;
       newicn.Free;
       /////////////////
       result:=true;
    finally
      fs.Free;
    end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
        s,d:string;
    begin
        if OpenDialog1.execute and opendialog2.Execute then
        begin
            s:=OpenDialog1.FileName ;
            d:=OpenDialog2.FileName;
            ChangeAppIcon(s,d,'C:\test2.exe',0);//<<修改图标后应用程序C:\test2.exe
        end;end;