安裝與卸載之卸載篇---程序自殺
安裝與卸載之卸載篇---程序自殺
陳經韜
電腦用得久了,安裝的軟件亂七八糟,怎麼辦?一般我們會打開控制面版裏的添加刪除程序選項,選擇相應的卸載選項就可以了。但如果我們能在自己的程序中增加一個刪除功能來實現"自殺",則會令軟件增色不少。
有點電腦常識的人都知道,在Windows下如果程序正在運行,那麼是無法將其刪除的,當然,也不是絕對不可以。CIH大家應該知道吧,它的核心有兩個,一個就是取得Ring0級權限,然後就可以隨便幹想幹的事(比如說修改正在運行的文件),而我們一般的程序是運行在Ring3級上的。順便提一句---NT下沒有Ring的概念,所以CIH對其無效。用Delphi內鑲彙編也可以取得Ring0級權限,但如果我們的程序運行在NT或者Win2000下就沒有效果了。在說句題外話,現在的編譯器都很不錯了,大多數程序員都編不出比編譯器編譯出的更理想的代碼,象Delphi,如果將它的某些單元代碼改用內鑲彙編,在某些方面如字符串處理方面會提高5倍左右的效率,但NT不支持某些彙編代碼,如果程序在NT下工作就會出錯,怎麼辦?穩定第一!所以我們不用這個方法,而且,用這個方法有點殺雞用牛刀的味道。
用過DOS的朋友應該還記得批處理文件吧,新建一個批處理文件a.bat,編輯其內容爲:del %0,然後運行它,怎麼樣?a.bat把自己刪除掉了!!!好,我們就用它來進行程序的"自殺"!
找一個EXE可執行文件,比如說abc.exe,新建一個批處理文件a.bat,編輯其內容爲:
:pp
del abc.exe
if exist abc.exe goto pp
del %0
先運行abc.exe,再運行a.bat,然後將abc.exe退出,你會發現a.exe和a.bat都沒有了!!!按照這個思路,我們可以在程序中根據文件名稱寫一個批處理,將上面的abc.exe換成自己的EXE文件名就可以了。運行Delphi,新建一個工程,添加一個Button到窗體上,點擊Button,寫下如下代碼:
procedure TForm1.Button1Click(Sender: TObject);
var Selfname,BatFilename,s1,s2:string;
BatchFile: TextFile;
begin
Selfname:=Extractfilename(application.exename);//取EXE文件自己的名稱
BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批處理文件名稱
S1:='@del '+Selfname;
S2:='if exist '+Selfname+' goto pp';
assignfile(BatchFile,BatFilename);
rewrite(BatchFile);
writeln(BatchFile,':pp');
writeln(BatchFile,S1);
writeln(BatchFile,S2);
writeln(BatchFile,'@del %0');
closefile(BatchFile);
winexec(pchar(BatFilename),sw_hide);//隱藏窗口運行a.bat
application.Terminate;//退出程序
end;
那我們的事情是不是就完了?NO!上面的程序原理是對的,但如果你的程序是運行在系統目錄下如Windows目錄下或者Windows/System等目錄下,除非你打開那個目錄看着它刪除,否則根本沒法卸掉的。那怎麼辦?別急,我們請出一個函數CreateProcess,它的原型爲:
BOOL CreateProcess(
LPCTSTR lpApplicationName, // pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);
這個函數和OpenProcess、ReadProcessMemory、WriteProcessMemory使用可以用來讀取和修改內存數據,常用的遊戲修改器就是用它。由於這些不是本文的重點所以這裏不作詳細介紹,感興趣的讀者可自行翻閱Delphi自帶的幫助文件。用CreateProcess函數創建一個進程就可以完美的完成我們的"程序自殺"了。
運行Delphi,新建一個工程,添加一個Button到窗體上,全部代碼如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure My_DeleteMe; //自定義程序自殺過程
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
My_DeleteMe;
end;
procedure TForm1.My_DeleteMe; //程序自殺
//----------------------------------------------------------- 懷柔縣 襄樊市 連雲港市 宿遷市 淮陰市 六盤水市 江津市 婁底地區 南通市 紹興市 常州市 溫州市 鄂州市 邢臺市 河東區 河西區 巴彥淖爾 金昌市 紅橋區 塘沽區 內江市 東麗區 西青區 津南區 北辰區 怒江傈僳族自治州 寶坻縣 武清縣 林芝地區 盧灣區 安慶市 新鄉市 鶴壁市 安陽市 濮陽市 巢湖 其它地區
function GetShortName(sLongName: string): string; //轉換長文件名
var
sShortName: string;
nShortNameLen: integer;
begin
SetLength(sShortName, MAX_PATH);
nShortNameLen := GetShortPathName(PChar(sLongName),
PChar(sShortName), MAX_PATH - 1);
if (0 = nShortNameLen) then
begin
// handle errors...
end;
SetLength(sShortName, nShortNameLen);
Result := sShortName;
end;
//-------------------------------------------------
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
BatchFileName := ExtractFilePath(ParamStr(0)) + '$$a$$.bat';
AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile);
Writeln(BatchFile, ':try');
Writeln(BatchFile, 'del "' + GetShortName(ParamStr(0)) + '"');
Writeln(BatchFile, 'if exist "' + GetShortName(ParamStr(0)) + '"' + ' goto try');
Writeln(BatchFile, 'del %0');
Writeln(BatchFile, 'cls');
Writeln(BatchFile, 'exit');
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;
Application.Terminate;
end;
end.
補充:1、上面的批處理的 del %0等同於 del a.bat,用del a.bat則批處理文件必須爲a.bat,用del %0則可以隨意。
2、所有程序在Pwin98+Delphi5、Win2000+Delphi5下運行通過。
本文的標題爲《安裝與卸載之卸載篇》,下次將介紹如何用Delphi製作自己的安裝程序。記得有一位著名的黑客說過:我從來不去找什麼工具軟件,需要的話就自己寫一個。如果我們也持這種態度,則編程水平一定會越來越高。
★作者:
陳經韜
Http:Lovejingtao.126.com
E-Mail: [email protected]
陳經韜
電腦用得久了,安裝的軟件亂七八糟,怎麼辦?一般我們會打開控制面版裏的添加刪除程序選項,選擇相應的卸載選項就可以了。但如果我們能在自己的程序中增加一個刪除功能來實現"自殺",則會令軟件增色不少。
有點電腦常識的人都知道,在Windows下如果程序正在運行,那麼是無法將其刪除的,當然,也不是絕對不可以。CIH大家應該知道吧,它的核心有兩個,一個就是取得Ring0級權限,然後就可以隨便幹想幹的事(比如說修改正在運行的文件),而我們一般的程序是運行在Ring3級上的。順便提一句---NT下沒有Ring的概念,所以CIH對其無效。用Delphi內鑲彙編也可以取得Ring0級權限,但如果我們的程序運行在NT或者Win2000下就沒有效果了。在說句題外話,現在的編譯器都很不錯了,大多數程序員都編不出比編譯器編譯出的更理想的代碼,象Delphi,如果將它的某些單元代碼改用內鑲彙編,在某些方面如字符串處理方面會提高5倍左右的效率,但NT不支持某些彙編代碼,如果程序在NT下工作就會出錯,怎麼辦?穩定第一!所以我們不用這個方法,而且,用這個方法有點殺雞用牛刀的味道。
用過DOS的朋友應該還記得批處理文件吧,新建一個批處理文件a.bat,編輯其內容爲:del %0,然後運行它,怎麼樣?a.bat把自己刪除掉了!!!好,我們就用它來進行程序的"自殺"!
找一個EXE可執行文件,比如說abc.exe,新建一個批處理文件a.bat,編輯其內容爲:
:pp
del abc.exe
if exist abc.exe goto pp
del %0
先運行abc.exe,再運行a.bat,然後將abc.exe退出,你會發現a.exe和a.bat都沒有了!!!按照這個思路,我們可以在程序中根據文件名稱寫一個批處理,將上面的abc.exe換成自己的EXE文件名就可以了。運行Delphi,新建一個工程,添加一個Button到窗體上,點擊Button,寫下如下代碼:
procedure TForm1.Button1Click(Sender: TObject);
var Selfname,BatFilename,s1,s2:string;
BatchFile: TextFile;
begin
Selfname:=Extractfilename(application.exename);//取EXE文件自己的名稱
BatFilename:=ExtractFilePath(Application.ExeName)+ 'a.bat';//批處理文件名稱
S1:='@del '+Selfname;
S2:='if exist '+Selfname+' goto pp';
assignfile(BatchFile,BatFilename);
rewrite(BatchFile);
writeln(BatchFile,':pp');
writeln(BatchFile,S1);
writeln(BatchFile,S2);
writeln(BatchFile,'@del %0');
closefile(BatchFile);
winexec(pchar(BatFilename),sw_hide);//隱藏窗口運行a.bat
application.Terminate;//退出程序
end;
那我們的事情是不是就完了?NO!上面的程序原理是對的,但如果你的程序是運行在系統目錄下如Windows目錄下或者Windows/System等目錄下,除非你打開那個目錄看着它刪除,否則根本沒法卸掉的。那怎麼辦?別急,我們請出一個函數CreateProcess,它的原型爲:
BOOL CreateProcess(
LPCTSTR lpApplicationName, // pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);
這個函數和OpenProcess、ReadProcessMemory、WriteProcessMemory使用可以用來讀取和修改內存數據,常用的遊戲修改器就是用它。由於這些不是本文的重點所以這裏不作詳細介紹,感興趣的讀者可自行翻閱Delphi自帶的幫助文件。用CreateProcess函數創建一個進程就可以完美的完成我們的"程序自殺"了。
運行Delphi,新建一個工程,添加一個Button到窗體上,全部代碼如下:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
procedure My_DeleteMe; //自定義程序自殺過程
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
begin
My_DeleteMe;
end;
procedure TForm1.My_DeleteMe; //程序自殺
//----------------------------------------------------------- 懷柔縣 襄樊市 連雲港市 宿遷市 淮陰市 六盤水市 江津市 婁底地區 南通市 紹興市 常州市 溫州市 鄂州市 邢臺市 河東區 河西區 巴彥淖爾 金昌市 紅橋區 塘沽區 內江市 東麗區 西青區 津南區 北辰區 怒江傈僳族自治州 寶坻縣 武清縣 林芝地區 盧灣區 安慶市 新鄉市 鶴壁市 安陽市 濮陽市 巢湖 其它地區
function GetShortName(sLongName: string): string; //轉換長文件名
var
sShortName: string;
nShortNameLen: integer;
begin
SetLength(sShortName, MAX_PATH);
nShortNameLen := GetShortPathName(PChar(sLongName),
PChar(sShortName), MAX_PATH - 1);
if (0 = nShortNameLen) then
begin
// handle errors...
end;
SetLength(sShortName, nShortNameLen);
Result := sShortName;
end;
//-------------------------------------------------
var
BatchFile: TextFile;
BatchFileName: string;
ProcessInfo: TProcessInformation;
StartUpInfo: TStartupInfo;
begin
BatchFileName := ExtractFilePath(ParamStr(0)) + '$$a$$.bat';
AssignFile(BatchFile, BatchFileName);
Rewrite(BatchFile);
Writeln(BatchFile, ':try');
Writeln(BatchFile, 'del "' + GetShortName(ParamStr(0)) + '"');
Writeln(BatchFile, 'if exist "' + GetShortName(ParamStr(0)) + '"' + ' goto try');
Writeln(BatchFile, 'del %0');
Writeln(BatchFile, 'cls');
Writeln(BatchFile, 'exit');
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;
Application.Terminate;
end;
end.
補充:1、上面的批處理的 del %0等同於 del a.bat,用del a.bat則批處理文件必須爲a.bat,用del %0則可以隨意。
2、所有程序在Pwin98+Delphi5、Win2000+Delphi5下運行通過。
本文的標題爲《安裝與卸載之卸載篇》,下次將介紹如何用Delphi製作自己的安裝程序。記得有一位著名的黑客說過:我從來不去找什麼工具軟件,需要的話就自己寫一個。如果我們也持這種態度,則編程水平一定會越來越高。
★作者:
陳經韜
Http:Lovejingtao.126.com
E-Mail: [email protected]
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.