異常死亡程式的自動復活 (轉)

subid發表於2007-08-12
異常死亡程式的自動復活 (轉)[@more@]
異常死亡程式的自動復活


一、問題的產生
我們或多或少都有這樣的經歷,在上執行的應用常常會異常終止,需要透過手工重新將其啟動起來。若無人看守,異常終止的程式不能實時啟動,則可能給生產造成損失。
本人在開發GPS全球衛星定位控制中心程式時,就遇到過控制中心程式異常終止死亡的情況,由此,找出了一個自動復活死亡程式的方法,供參考。
二、相關知識
通常,把一個應用程式的一次執行例項叫做一個程式,在一個程式內又可包含多條可併發的路徑,每條執行路徑叫做一個執行緒,一個程式至少包含一個主執行緒。主執行緒負責執行執行的啟動程式碼。另外,一個程式可以建立若干子程式。當程式被建立時,系統自動產生主執行緒,主執行緒然後可建立更多的執行緒。
我們可以編寫一個程式,讓其建立、啟動子程式,並監視程式的執行情況,在其出現異常終止時,立即重新建立並啟動子程式即可。
三、相關  
1、建立一個子程式函式:
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,  
D dwCreationFlags,  
LPVOID lpEnvironment,  
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,  
LPPROCESS_INFORMATION lpProcessInformation  
);
引數說明:
lpApplicationName:新程式將要使用的可執行的名字,必須包含副檔名。
LpCommandLine:新程式的命令列。若lpApplicationName為NULL,LpCommandLine 的第一個引數是新程式將要使用的可執行檔案的名字,可以不包含副檔名,系統假定是exe檔案。
LpProcessAttributes和lpThreadAttributes:分別是給程式和執行緒物件指定的屬性。
BInheritHandles:指定該程式是否繼承其父程式中的控制程式碼。
dwCreationFlags:指定新程式產生方式的標誌,可用邏輯運算子or相連線。
LpEnvironment:指向含有新程式將要使用的環境塊字串的一塊,一般為NULL,使子程式繼承父程式的一組環境塊。
LpCurrentDirectory:設定子程式的當前器和工作目錄, 為NULL,子程式繼承父程式的當前驅動器和工作目錄。
LpStartupInfo:指向STARTUPINFO 的結構。一般讓子程式使用預設值。但要把該結構中的所有成員初始化為0,並設定cb為結構大小。
STARTUPINFO 結構如下:
typedef struct _STARTUPINFO {  
DWORD cb;  
LPTSTR lpReserved;  
LPTSTR lpDesktop;  
LPTSTR lpTitle;  
DWORD dwX;  
DWORD dwY;  
DWORD dwXSize;  
DWORD dwYSize;  
DWORD dwXCountChars;  
DWORD dwYCountChars;  
DWORD dwFillAttribute;  
DWORD dwFlags;  
WORD wShowWindow;  
WORD cbReserved2;  
LPBYTE lpReserved2;  
HANDLE hStdInput;  
HANDLE hStdOutput;  
HANDLE hStdError;  
} STARTUPINFO, *LPSTARTUPINFO;
lpProcessInformation 引數指向LPPROCESS_INFORMATION結構,CreateProcess在返回之前,填入有關子程式的資訊,父程式正是利用該資訊監測子程式是否終止。該結構如下:
typedef struct _PROCESS_INFORMATION {  
HANDLE hProcess;  
HANDLE hThread;  
DWORD dwProcessId;  
DWORD dwThreadId;  
} PROCESS_INFORMATION;  
hProcess和hThread分別是子程式的控制程式碼和子程式的主執行緒的控制程式碼,dwProcessId和dwThreadId分別是子程式的標識號和子程式的主執行緒的標識號。  
2、子程式終止檢測函式
GetEXitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode );
Hprocess:程式控制程式碼,lpExitCode:程式終止時的退出碼。
如果一個程式沒有終止,lpExitCode 的返回值是STILL_ACTIVE,否則返回其他值。
四、方法的5語言實現
1、建立一個新的專案 Project1
選擇File,New Application。在表單Form1上放一Memo,一個OK按鈕元件,改變OK按鈕元件的Cation屬性為 CreateProcess。再放一個timer元件。設定timer元件的Interval值為1000,每秒檢查一次程式是否終止。
2、在Unit1 Use節的Type後定義一個過程
procedure EstablishProcess;
在Unit1 Use節的Var後定義一個變數:
piProcInfoGPS:PROCESS_INFORMATION;
3、在Unit1 implementation節中編寫EstablishProcess過程的實現程式碼如下:
procedure EstablishProcess;
Var
siStartupInfo:STARTUPINFO;
saProcess,saThread:SECURITY_ATTRIBUTES;
fSuccess:boolean;
begin
fSuccess:=false;
ZeroMemory(@siStartupInfo,sizeof(siStartupInfo));
siStartupInfo.cb:=sizeof(siStartupInfo);
saProcess.nLength:=sizeof(saProcess);
saProcess.lpSecurityDescriptor:=PChar(nil);
saProcess.bInheritHandle:=true;
saThread.nLength:=sizeof(saThread);
saThread.lpSecurityDescriptor:=PChar(nil);
saThread.bInheritHandle:=true;
fSuccess:=CreateProcess(PChar(nil),'c:sr350Sr350buff',@saProcess,@saThread,false,
CREATE_DEFAULT_ERROR_MODE,Pchar(nil),Pchar(nil),siStartupInfo,piProcInfoGPS);
if( not fSuccess)then
Form1.Memo1.Lines.Add('Create Process Sr350buff fail.')
else
Form1.Memo1.Lines.Add('Create Process Sr350buff success.')
end;
4、在CreateProcess按鈕的OnClick事件中過程
EstablishProcess;
5、為Timer1的OnTimer事件編寫程式碼:
Procedure TForm1.Timer1Timer(Sender: T);
Var
dwExitCode:DWORD;
fprocessExit:boolean;
Begin
?  
dwExitCode:=0;
fprocessExit:=false;
fprocessExit:=GetExitCodeProcess(piProcInfoGPS.hProcess,dwExitCode);
if(fprocessExit and (dwExitCode<>STILL_ACTIVE))then
begin
Memo1.Lines.Add('SR350buff.exe程式終止');
CloseHandle(piProcInfoGPS.hThread);
CloseHandle(piProcInfoGPS.hProcess);
EstablishProcess;
end;
End;
6、程式中設可執行檔名為c:sr350sr350buff.exe,所以c:盤sr350目錄下需有sr350buff.exe檔案。
7、編譯聯接,執行project1,單擊CreateProcess可見c:sr350sr350buff.exe啟動。關掉sr350buff.exe程式,可見sr350buff.exe自動再啟動。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10796304/viewspace-952182/,如需轉載,請註明出處,否則將追究法律責任。

相關文章