监控指定进程

对于守护中间件是非常有用的。中间件不可能绝对的稳定而不出问题,中间件有可能因比较严重的错误导致当机或者进程被人为地错误地关闭了中间件。

有了这个自动守护进程的存在,这一切的问题都可以迎刃而解。

program Monitor;

// {$APPTYPE CONSOLE}

uses
Winapi.Windows,
System.SysUtils,
ProcLib in 'ProcLib.pas';

var
Mutex, h: HWND;

const
c_AppName = 'server.exe';
c_ClassName = 'Tf_MainForm';

begin
Mutex := Winapi.Windows.CreateMutex(nil, False, 'Monitor');
if (GetLastError = ERROR_ALREADY_EXISTS) or (Mutex = 0) then
Exit;

G_ExeFile := ExtractFilePath(ParamStr(0)) + c_AppName;

while True do
begin
Sleep(2000);
if ProcessRunning(c_AppName) then
begin
h := FindWindow(PChar(c_ClassName), nil);
if (not IsAppRespondig(h)) and (h <> 0) then
begin
KillTask(c_AppName);
Continue;
end
else
Continue;
end;

if G_ExeFile = '' then
Continue;

Exec(G_ExeFile);
end;

end.

 

unit ProcLib;

interface

uses
Winapi.Windows, System.SysUtils, Winapi.PsAPI,
Winapi.TlHelp32, Winapi.ShellAPI, Winapi.Messages, Vcl.Dialogs;

function ProcessRunning(ExeName: string): Boolean; // 指定进程是否正在运行
procedure Exec(FileName: string); // 开启指定进程
function KillTask(ExeFileName: String): Integer; // 关闭进程
function IsAppRespondig(wnd: HWND): Boolean; // 进程是否有反应

var
G_ExeFile: string = '';

implementation

function IsAppRespondig9X(dwThreadId: DWORD): Boolean;
type
TIsHungThread = function(dwThreadId: DWORD): BOOL; stdcall;
var
hUser32: THandle;
IsHungThread: TIsHungThread;
begin
Result := True;
hUser32 := GetModuleHandle('user32.dll');
if (hUser32 > 0) then
begin
@IsHungThread := GetProcAddress(hUser32, 'IsHungThread');
if Assigned(IsHungThread) then
begin
Result := not IsHungThread(dwThreadId);
end;
end;
end;

function IsAppRespondigNT(wnd: HWND): Boolean;
type
TIsHungAppWindow = function(wnd: HWND): BOOL; stdcall;
var
hUser32: THandle;
IsHungAppWindow: TIsHungAppWindow;
begin
Result := True;
hUser32 := GetModuleHandle('user32.dll');
if (hUser32 > 0) then
begin
@IsHungAppWindow := GetProcAddress(hUser32, 'IsHungAppWindow');
if Assigned(IsHungAppWindow) then
begin
Result := not IsHungAppWindow(wnd);
end;
end;
end;

function IsAppRespondig(wnd: HWND): Boolean;
begin
Result := False;
if not IsWindow(wnd) then
begin
ShowMessage('Incorrect window handle!');
Exit;
end;
if Win32Platform = VER_PLATFORM_WIN32_NT then
Result := IsAppRespondigNT(wnd)
else
Result := IsAppRespondig9X(GetWindowThreadProcessId(wnd, nil));
end;

function KillTask(ExeFileName: String): Integer;
const
PROCESS_TERMINATE = $0001;
var
ContinueLoop: Boolean;
FSnapshotHandle: THandle;
FProcessEntry32: TProcessEntry32;
begin
Result := 0;
FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);

while Integer(ContinueLoop) <> 0 do
begin
If ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile))
= UpperCase(ExeFileName)) Or (UpperCase(FProcessEntry32.szExeFile)
= UpperCase(ExeFileName))) then
Result := Integer(TerminateProcess(OpenProcess(PROCESS_TERMINATE, BOOL(0),
FProcessEntry32.th32ProcessID), 0));
ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);
end;

function ProcessFileName(PID: DWORD): string;
var
Handle: THandle;
begin
Result := '';
Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ,
False, PID);
if Handle <> 0 then
try
SetLength(Result, MAX_PATH);
if GetModuleFileNameEx(Handle, 0, PChar(Result), MAX_PATH) > 0 then
SetLength(Result, StrLen(PChar(Result)))
else
Result := '';
finally
CloseHandle(Handle);
end;
end;

function ProcessRunning(ExeName: string): Boolean;
var
SnapProcHandle: THandle;
NextProc: Boolean;
ProcEntry: TProcessEntry32;
ProcFileName: string;
begin
Result := False;
SnapProcHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if SnapProcHandle = INVALID_HANDLE_VALUE then
Exit;

try
ProcEntry.dwSize := SizeOf(ProcEntry);
NextProc := Process32First(SnapProcHandle, ProcEntry);

while NextProc do
begin
if ProcEntry.th32ProcessID <> 0 then
begin
ProcFileName := ProcessFileName(ProcEntry.th32ProcessID);
if ProcFileName = '' then
ProcFileName := ProcEntry.szExeFile;

if SameText(ExtractFileName(ProcFileName), ExeName) then
begin
Result := True;
Break;
end;
end;
NextProc := Process32Next(SnapProcHandle, ProcEntry);
end;
finally
CloseHandle(SnapProcHandle);
end;
end;

procedure Exec(FileName: string);
var
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
FillChar(StartupInfo, SizeOf(StartupInfo), #0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOWDEFAULT;
if not CreateProcess(PChar(FileName), nil, nil, nil, False,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(FileName)), StartupInfo, ProcessInfo) then
Exit;
WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
end;

end.

http://www.cnblogs.com/hnxxcxg/archive/2013/02/21/2920453.html

posted @   findumars  Views(447)  Comments(0Edit  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2012-03-02 使用CRichEditCtrl与正则实现XML高亮编辑器
2012-03-02 两种方法查看MFC源代码
2012-03-02 LLVM CodeExtractor
点击右上角即可分享
微信分享提示