请问有没有办法让一个程序在执行结束时删除自身的执行文件??在线等待!!! 请问有没有办法让一个程序在执行结束时删除自身的执行文件??在线等待!!! 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 一般来说 是不行的,如果要的话,你可以找一找如何将一个线程写入explorer进程中,这样你的程序就等于可以依赖于explorer而存活,这时候你就可以干掉自己了。当然了,这好象在编一个什么破坏性的东西呀?或是自己想隐起来做什么呢? uses Windows, Dialogs, SysUtils, Controls;procedure DeleteMe(mDeleteDir: Boolean = False); { 自己删除自己 }var vExeDir: string; procedure pDelDir(mDirName: string); { 删除指定路径 } var vSearchRec: TSearchRec; PathName: string; K: Integer; begin PathName := mDirName + '\*.*'; K := FindFirst(PathName, faAnyFile, vSearchRec); while K = 0 do begin if (vSearchRec.Attr and faDirectory > 0) and (Pos(vSearchRec.Name, '..') = 0) then begin {$WARNINGS OFF} FileSetAttr(vSearchRec.Name, faDirectory); {$WARNINGS ON} pDelDir(mDirName + '\' + vSearchRec.Name); end else if (Pos(vSearchRec.Name, '..') = 0) and (CompareText(mDirName + '\' + vSearchRec.Name, ParamStr(0)) <> 0) then begin {$WARNINGS OFF} FileSetAttr(vSearchRec.Name, 0); {$WARNINGS ON} DeleteFile(PChar(mDirName + '\' + vSearchRec.Name)); end; K := FindNext(vSearchRec); end; if CompareText(vExeDir, mDirName) <> 0 then RmDir(mDirName); end; { pDelDir }var BatchFile: TextFile; BatchFileName: TFileName; ProcessInfo: TProcessInformation; StartUpInfo: TStartupInfo;begin vExeDir := ExtractFileDir(ParamStr(0)); if mDeleteDir then pDelDir(vExeDir); BatchFileName := '..\DeleteMe.bat'; AssignFile(BatchFile, BatchFileName); Rewrite(BatchFile); Writeln(BatchFile, ':del'); Writeln(BatchFile, 'del "' + ParamStr(0) + '"'); Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try'); if mDeleteDir then Writeln(BatchFile, 'rd ' + ExtractFileDir(ParamStr(0))); Writeln(BatchFile, 'del %0'); CloseFile(BatchFile); FillChar(StartUpInfo, SizeOf(StartUpInfo), #0); StartUpInfo.dwFlags := STARTF_USESHOWWINDOW; StartUpInfo.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(BatchFileName), nil, nil, False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo) then begin CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); end;end; { DeleteMe }///////End Source///////Begin Demobegin if MessageDlg('警告执行此程序将删除所在目录的所有文件及目录', mtWarning, [mbYes, mbNo], 0) = mrYes then DeleteMe(True);end.///////End Demo 给你一段资料:program Project1;uses Windows;procedure DeleteSelf;var hModule: THandle; buff: array[0..255] of Char; hKernel32: THandle; pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;begin hModule := GetModuleHandle(nil); GetModuleFileName(hModule, buff, sizeof(buff)); CloseHandle(THandle(4)); hKernel32 := GetModuleHandle('KERNEL32'); pExitProcess := GetProcAddress(hKernel32, 'ExitProcess'); pDeleteFileA := GetProcAddress(hKernel32, 'DeleteFileA'); pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile'); asm LEA EAX, buff PUSH 0 PUSH 0 PUSH EAX PUSH pExitProcess PUSH hModule PUSH pDeleteFileA PUSH pUnmapViewOfFile RET end;end;begin MessageBox(0,'Test','信息',MB_OK+MB_ICONINFORMATION); DeleteSelf;end.必须把代码放在一个Procedure里!**************下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码. 这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了. int main(int argc, char *argv[]) { HMODULE module = GetModuleHandle(0); CHAR buf[MAX_PATH]; GetModuleFileName(module, buf, sizeof buf); CloseHandle(HANDLE(4)); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push UnmapViewOfFile ret } return 0; } 现在,我们先看一下堆栈中的东西 偏移 内容 24 0 20 0 16 offset buf 12 address of ExitProcess 8 module 4 address of DeleteFile 0 address of UnmapViewOfFile 调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出错.而调用ExitProcess则应该不会返回. 这段代码的精妙之处在于: 1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄. 2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码. 3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.) #include Windows.hint main(int argc, char *argv[]) { HMODULE module = GetModuleHandle(0); CHAR buf[MAX_PATH]; GetModuleFileName(module, buf, sizeof(buf)); MessageBox(0,"Del Me","Test",MB_OK); CloseHandle((HANDLE)4); __asm { lea eax, buf push 0 push 0 push eax push ExitProcess push module push DeleteFile push UnmapViewOfFile ret } return 0; }采用vc++6.0的控制台模式编译运行该程序后自动把自己删掉 procedure DeleteMe;var BatchFile: TextFile; BatchFileName: string; ProcessInfo: TProcessInformation; StartUpInfo: TStartupInfo;begin BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat'; AssignFile(BatchFile, BatchFileName); Rewrite(BatchFile); Writeln(BatchFile, ':try'); Writeln(BatchFile, 'del "' + ParamStr(0) + '"'); Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try'); Writeln(BatchFile, 'del %0'); CloseFile(BatchFile); FillChar(StartUpInfo, SizeOf(StartUpInfo), $00); StartUpInfo.dwFlags := STARTF_USESHOWWINDOW; StartUpInfo.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(BatchFileName), nil, nil, False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo) then begin CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); end;end; procedure DeleteMe;var BatchFile: TextFile; BatchFileName: string; ProcessInfo: TProcessInformation; StartUpInfo: TStartupInfo;begin BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat'; AssignFile(BatchFile, BatchFileName); Rewrite(BatchFile); Writeln(BatchFile, ':try'); Writeln(BatchFile, 'del "' + ParamStr(0) + '"'); Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try'); Writeln(BatchFile, 'del %0'); CloseFile(BatchFile); FillChar(StartUpInfo, SizeOf(StartUpInfo), $00); StartUpInfo.dwFlags := STARTF_USESHOWWINDOW; StartUpInfo.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(BatchFileName), nil, nil, False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo, ProcessInfo) then begin CloseHandle(ProcessInfo.hThread); CloseHandle(ProcessInfo.hProcess); end;end; 如果只用一个exe文件的话,这样做恐怕没有什么希望!如果这个exe被装入内存中,还没有结束,这时候删除自身是不可能的。如果exe已经结束,这时候谁又来执行删除的操作呢? program Project1;uses Forms,Windows, Unit1 in 'Unit1.pas' {Form1};{$R *.res}procedure DeleteSelf;var hModule: THandle; buff: array[0..255] of Char; hKernel32: THandle; pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;begin hModule := GetModuleHandle(nil); GetModuleFileName(hModule, buff, sizeof(buff)); CloseHandle(THandle(4)); hKernel32 := GetModuleHandle('KERNEL32'); pExitProcess := GetProcAddress(hKernel32, 'ExitProcess'); pDeleteFileA := GetProcAddress(hKernel32, 'DeleteFileA'); pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile'); asm LEA EAX, buff PUSH 0 PUSH 0 PUSH EAX PUSH pExitProcess PUSH hModule PUSH pDeleteFileA PUSH pUnmapViewOfFile RET end;end;begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; DeleteSelf;end. me too,不要给我用BAT的例子,这个我会!!!另外,楼上上的兄弟,可否解释一下,您的代码?? BatchFile:TextFile;这个怎么用不起?????我的DELPHI老报错!! 送分 调用部外部EXE程序.进度条???? 请教:立体质感的方法 DLL调用clientsocket问题 怎样向局域网中的所有电脑传送文件(是单方的) 使用ShellExecute调用一个程序,如何知道该程序什么结束呢? dbgrideh控件如何安装? 字符串处理问题,急,帮帮忙!!! sql菜菜子,100大元 DELPHI 急啊,有谁这方面软件的近来看看 江湖告急!!!!!!!! 请问动态数组array使用完之后需要释放吗?
如果要的话,你可以找一找如何将一个线程写入explorer进程中,这样你的程序就等于可以依赖于explorer而存活,这时候你就可以干掉自己了。当然了,这好象在编一个什么破坏性的东西呀?或是自己想隐起来做什么呢?
Windows, Dialogs, SysUtils, Controls;procedure DeleteMe(mDeleteDir: Boolean = False); { 自己删除自己 }
var
vExeDir: string; procedure pDelDir(mDirName: string); { 删除指定路径 }
var
vSearchRec: TSearchRec;
PathName: string;
K: Integer;
begin
PathName := mDirName + '\*.*';
K := FindFirst(PathName, faAnyFile, vSearchRec);
while K = 0 do begin
if (vSearchRec.Attr and faDirectory > 0) and
(Pos(vSearchRec.Name, '..') = 0) then begin
{$WARNINGS OFF}
FileSetAttr(vSearchRec.Name, faDirectory);
{$WARNINGS ON}
pDelDir(mDirName + '\' + vSearchRec.Name);
end else if (Pos(vSearchRec.Name, '..') = 0) and
(CompareText(mDirName + '\' + vSearchRec.Name, ParamStr(0)) <> 0) then begin
{$WARNINGS OFF}
FileSetAttr(vSearchRec.Name, 0);
{$WARNINGS ON}
DeleteFile(PChar(mDirName + '\' + vSearchRec.Name));
end;
K := FindNext(vSearchRec);
end;
if CompareText(vExeDir, mDirName) <> 0 then RmDir(mDirName);
end; { pDelDir }var
BatchFile: TextFile;
BatchFileName: TFileName;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
vExeDir := ExtractFileDir(ParamStr(0));
if mDeleteDir then pDelDir(vExeDir);
BatchFileName := '..\DeleteMe.bat';
AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile);
Writeln(BatchFile, ':del');
Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
Writeln(BatchFile, 'if exist "' + ParamStr(0) + '"' + ' goto try');
if mDeleteDir then Writeln(BatchFile, 'rd ' + ExtractFileDir(ParamStr(0)));
Writeln(BatchFile, 'del %0');
CloseFile(BatchFile);
FillChar(StartUpInfo, SizeOf(StartUpInfo), #0);
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_HIDE;
if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
ProcessInfo) then begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end; { DeleteMe }
///////End Source///////Begin Demo
begin
if MessageDlg('警告执行此程序将删除所在目录的所有文件及目录',
mtWarning, [mbYes, mbNo], 0) = mrYes then
DeleteMe(True);
end.
///////End Demo
Windows;procedure DeleteSelf;
var
hModule: THandle;
buff: array[0..255] of Char;
hKernel32: THandle;
pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;
begin
hModule := GetModuleHandle(nil);
GetModuleFileName(hModule, buff, sizeof(buff));
CloseHandle(THandle(4));
hKernel32 := GetModuleHandle('KERNEL32');
pExitProcess := GetProcAddress(hKernel32, 'ExitProcess');
pDeleteFileA := GetProcAddress(hKernel32, 'DeleteFileA');
pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile');
asm
LEA EAX, buff
PUSH 0
PUSH 0
PUSH EAX
PUSH pExitProcess
PUSH hModule
PUSH pDeleteFileA
PUSH pUnmapViewOfFile
RET
end;
end;begin
MessageBox(0,'Test','信息',MB_OK+MB_ICONINFORMATION);
DeleteSelf;
end.
必须把代码放在一个Procedure里!
**************
下面的代码由Gary Nebbett写就.Gary Nebbett乃是WINDOWS NT/2000 NATIVE API REFERENCE的作者.乃NT系统一等一的高手.下面就分析一些他的这段代码.
这段代码在PROCESS没有结束前就将启动PROCESS的EXE文件删除了.
int main(int argc, char *argv[])
{
HMODULE module = GetModuleHandle(0);
CHAR buf[MAX_PATH];
GetModuleFileName(module, buf, sizeof buf);
CloseHandle(HANDLE(4));
__asm {
lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push UnmapViewOfFile
ret
}
return 0;
}
现在,我们先看一下堆栈中的东西 偏移 内容
24 0
20 0
16 offset buf
12 address of ExitProcess
8 module
4 address of DeleteFile
0 address of UnmapViewOfFile 调用RET返回到了UnmapViewOfFile,也就是栈里的偏移0所指的地方.当进入UnmapViewOfFile的流程时,栈里见到的是返回地址DeleteFile和HMODUL module.也就是说调用完毕后返回到了DeleteFile的入口地址.当返回到DeleteFile时,看到了ExitProcess的地址,也就是返回地址.和参数EAX,而EAX则是buffer.buffer存的是EXE的文件名.由GetModuleFileName(module, buf, sizeof buf)返回得到.执行了DeleteFile后,就返回到了ExitProcess的函数入口.并且参数为0而返回地址也是0.0是个非法地址.如果返回到地址0则会出错.而调用ExitProcess则应该不会返回.
这段代码的精妙之处在于:
1.如果有文件的HANDLE打开,文件删除就会失败,所以,CloseHandle(HANDLE(4));是十分巧妙的一手.HANDLE4是OS的硬编码,对应于EXE的IMAGE.在缺省情况下,OS假定没有任何调用会关闭IMAGE SECTION的HANDLE,而现在,该HANDLE被关闭了.删除文件就解除了文件对应的一个句柄.
2.由于UnmapViewOfFile解除了另外一个对应IMAGE的HANDLE,而且解除了IMAGE在内存的映射.所以,后面的任何代码都不可以引用IMAGE映射地址内的任何代码.否则就OS会报错.而现在的代码在UnmapViewOfFile后则刚好没有引用到任何IMAGE内的代码.
3.在ExitProcess之前,EXE文件就被删除了.也就是说,进程尚在,而主线程所在的EXE文件已经没了.(WINNT/9X都保护这些被映射到内存的WIN32 IMAGE不被删除.)
#include Windows.hint main(int argc, char *argv[])
{
HMODULE module = GetModuleHandle(0);
CHAR buf[MAX_PATH];
GetModuleFileName(module, buf, sizeof(buf));
MessageBox(0,"Del Me","Test",MB_OK);
CloseHandle((HANDLE)4);
__asm {
lea eax, buf
push 0
push 0
push eax
push ExitProcess
push module
push DeleteFile
push UnmapViewOfFile
ret
}
return 0;
}
采用vc++6.0的控制台模式编译
运行该程序后自动把自己删掉
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat'; AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile); Writeln(BatchFile, ':try');
Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
Writeln(BatchFile,
'if exist "' + ParamStr(0) + '"' + ' goto try');
Writeln(BatchFile, 'del %0');
CloseFile(BatchFile); FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
BatchFileName := ExtractFilePath(ParamStr(0)) + '_deleteme.bat'; AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile); Writeln(BatchFile, ':try');
Writeln(BatchFile, 'del "' + ParamStr(0) + '"');
Writeln(BatchFile,
'if exist "' + ParamStr(0) + '"' + ' goto try');
Writeln(BatchFile, 'del %0');
CloseFile(BatchFile); FillChar(StartUpInfo, SizeOf(StartUpInfo), $00);
StartUpInfo.dwFlags := STARTF_USESHOWWINDOW;
StartUpInfo.wShowWindow := SW_HIDE; if CreateProcess(nil, PChar(BatchFileName), nil, nil,
False, IDLE_PRIORITY_CLASS, nil, nil, StartUpInfo,
ProcessInfo) then
begin
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;
Forms,Windows,
Unit1 in 'Unit1.pas' {Form1};{$R *.res}
procedure DeleteSelf;
var
hModule: THandle;
buff: array[0..255] of Char;
hKernel32: THandle;
pExitProcess, pDeleteFileA, pUnmapViewOfFile: Pointer;
begin
hModule := GetModuleHandle(nil);
GetModuleFileName(hModule, buff, sizeof(buff));
CloseHandle(THandle(4));
hKernel32 := GetModuleHandle('KERNEL32');
pExitProcess := GetProcAddress(hKernel32, 'ExitProcess');
pDeleteFileA := GetProcAddress(hKernel32, 'DeleteFileA');
pUnmapViewOfFile := GetProcAddress(hKernel32, 'UnmapViewOfFile');
asm
LEA EAX, buff
PUSH 0
PUSH 0
PUSH EAX
PUSH pExitProcess
PUSH hModule
PUSH pDeleteFileA
PUSH pUnmapViewOfFile
RET
end;
end;
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
DeleteSelf;
end.