Mega Code Archive

 
Categories / Delphi / Examples
 

Process viewer component

A Component that shows all running processes, not only on WinNT but also on windows 98/95 ! A Component that shows all running processes, not only on WinNT but also on windows 98/95 ! It also has a public method calld KillSelectedProcess, I guess you can figure out what it does... It has saved me a lot of trouble and saved me a lot of needs to reboot my system on my windows98 machine... well, here's the source for it : What you will have to do is make a new unit, copy this text in it and save the unit as ggProcessViewer. Then you can install in into your component pallet by using the delphi main menu, Component/Install Component... Have a lot of fun... unit ggProcessViewer; interface uses Windows, SysUtils, Classes, Controls, Grids, ExtCtrls, messages, tlHelp32, Dialogs; type //NT Functions for getting the process information : TEnumProcesses = function(lpidProcess: LPDWORD; cb: DWORD; var cbNeeded: DWORD): BOOL; StdCall; //external cPSAPIDLL; TGetModuleBaseNameA = function(hProcess: THandle; hModule: HMODULE; lpBaseName: PAnsiChar; nSize: DWORD): DWORD; StdCall; //external cPSAPIDLL; TGetModuleFileNameExA = function(hProcess: THandle; hModule: HMODULE; lpFilename: PAnsiChar; nSize: DWORD): DWORD; StdCall; //external cPSAPIDLL; TEnumProcessModules = function (hProcess: THandle; lphModule: LPDWORD; cb: DWORD; var lpcbNeeded: DWORD): BOOL; StdCall; //external cPSAPIDLL; TPByte = ^TByte; TByte = array[0..0] of byte; ThackWinControl = class(TWinControl) public property Text; end; ThackGraphicControl = class(TGraphicControl) public property Caption; end; TProcessTimeType = (ptCreationTime, ptExitTime, ptKernelTime, ptUserTime, ptCPUTime); TAfterRefreshProcesses = procedure(Sender: TObject) of object; TBeforeRefreshProcesses = procedure(Sender: TObject) of object; TggProcessViewer = class(TStringGrid) private FProcessCount : integer; FAutoRefresh : boolean; FAfterRefreshProcesses : TAfterRefreshProcesses; FBeforeRefreshProcesses : TBeforeRefreshProcesses; RefreshTimer : TTimer; procedure InitGridForNT; procedure Getprocesses; procedure GetProcessesOnNT; function SetProcessCount: integer; procedure GetProcessCount(const Value: integer); procedure GetTheProcessTimes(PID: integer); procedure SetAutoRefresh(const Value: boolean); procedure TimerAutoRefresh(Sender: TObject); procedure InitGridForWinXX; procedure GetProcessesOnWinXX; protected //Adress holders of the procedures for NT EnumProcesses : TEnumProcesses; GetModuleBaseNameA : TGetModuleBaseNameA; GetModuleFileNameExA : TGetModuleFileNameExA; EnumProcessModules : TEnumProcessModules; public constructor Create(AOwner: TComponent); override; destructor Destroy; override; procedure Refresh; procedure KillSelectedProcess; published property DoubleBuffered; property ProcessCount: Integer read SetProcessCount write GetProcessCount; property AutoRefresh: Boolean read FAutoRefresh write SetAutoRefresh; property AfterRefreshProcesses: TAfterRefreshProcesses read FAfterRefreshProcesses write FAfterRefreshProcesses; property BeforeRefreshProcesses: TBeforeRefreshProcesses read FBeforeRefreshProcesses write FBeforeRefreshProcesses; end; procedure Register; const cPSAPIDLL = 'PSAPI.dll'; ProcessBasicInformation = 0; implementation procedure Register; begin RegisterComponents('GuidoG', [TggProcessViewer]); end; { TggProcessViewer } constructor TggProcessViewer.Create(AOwner: TComponent); begin inherited; RefreshTimer := TTimer.Create(Self); RefreshTimer.OnTimer := TimerAutoRefresh; FixedCols := 0; DefaultRowHeight := 15; ColWidths[0] := 120; ColWidths[1] := 60; ColWidths[2] := 50; ColWidths[3] := 360; Options := Options - [goVertLine, goHorzLine] + [goDrawFocusSelected, goThumbTracking, goColSizing, goRowSizing]; GetProcesses; FAutoRefresh := TRUE; end; procedure TggProcessViewer.InitGridForNT; begin ColCount := 7; RowCount := 2; Cells[0, 0] := 'Process'; Cells[1, 0] := 'PID'; Cells[2, 0] := 'CPU time'; Cells[3, 0] := 'Kernel time'; Cells[4, 0] := 'User time'; Cells[5, 0] := 'Priority'; Cells[6, 0] := 'Location'; Cells[0, 1] := ''; Cells[1, 1] := ''; Cells[2, 1] := ''; Cells[3, 1] := ''; Cells[4, 1] := ''; Cells[5, 1] := ''; Cells[6, 1] := ''; end; procedure TggProcessViewer.InitGridForWinXX; begin ColCount := 4; RowCount := 2; Cells[0, 0] := 'Process'; Cells[1, 0] := 'PID'; Cells[2, 0] := 'Priority'; Cells[3, 0] := 'Location'; Cells[0, 1] := ''; Cells[1, 1] := ''; Cells[2, 1] := ''; Cells[3, 1] := ''; end; procedure TggProcessViewer.GetProcessesOnNT; var I : Integer; pidNeeded : DWORD; PIDList : array[0..1000] of Integer; PIDName : array [0..MAX_PATH - 1] of char; PH : THandle; hMod : HMODULE; dwSize2 : DWORD; J, ColBeforeRefresh : integer; PIDContentsBeforeRefresh : string; begin ColBeforeRefresh := Col; PIDContentsBeforeRefresh := Cells[1, Row]; Perform(WM_SETREDRAW, 0, 0); try InitGridForNT; if not EnumProcesses(@PIDList, 1000, pidNeeded) then raise Exception.Create('PSAPI.DLL not found! Are you sure you ' + 'are running windows NT/Y2K ?'); for i := 0 to (pidNeeded div SizeOf (Integer)- 1) do begin PH := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, FALSE, PIDList[I]); if PH <> 0 then begin if GetModuleFileNameExA(PH, 0, PIDName, SizeOf(PIDName)) > 0 then begin if EnumProcessModules(PH, @hMod, SizeOf(hMod), dwSize2) then begin GetModuleFileNameExA(PH, hMod, PIDName, SizeOf(PIDName)); Cells[0, RowCount - 1] := ExtractFileName(PIDName); Cells[1, RowCount - 1] := IntToStr(PIDList[I]); GetTheProcessTimes(PIDList[I]); case GetPriorityClass(PH) of HIGH_PRIORITY_CLASS: Cells[5, RowCount - 1] := 'High'; IDLE_PRIORITY_CLASS: Cells[5, RowCount - 1] := 'Idle'; NORMAL_PRIORITY_CLASS: Cells[5, RowCount - 1] := 'Normal'; REALTIME_PRIORITY_CLASS : Cells[5, RowCount - 1] := 'RealTime'; end; Cells[6, RowCount - 1] := ExtractFilePath(PIDName); end; RowCount := RowCount + 1; CloseHandle(PH); end; end; end; if RowCount > 2 then RowCount := RowCount - 1; FProcessCount := RowCount - 1; for J := 1 to RowCount - 1 do if Cells[1, J] = PIDContentsBeforeRefresh then begin Col := ColBeforeRefresh; Row := J; Break; end; finally Perform(WM_SETREDRAW, 1, 0); Invalidate; end; end; procedure TggProcessViewer.GetTheProcessTimes(PID: integer); var lpLocalFileTime : TFileTime; lpSystemTime : TSystemTime; PH : THandle; hProcess : THandle; lpCreationTime, lpExitTime, lpKernelTime, lpUserTime : TFileTime; KernelDay, UserDay : integer; KernelTime, UserTime : TDateTime; Result, strHours : string; begin Result := 'n/a'; hProcess := PID; PH := OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, hProcess); if PH <> 0 then try GetProcessTimes(PH, lpCreationTime, lpExitTime, lpKernelTime, lpUserTime); FileTimeToLocalFileTime(lpCreationTime, lpLocalFileTime); //Get the kernel time and format it FileTimeToSystemTime(lpKernelTime, lpSystemTime); KernelDay := lpSystemTime.wDay; KernelTime := SystemTimeToDateTime(lpSystemTime); Result := TimeToStr(KernelTime); strHours := Copy(Result, 1, Pos(':', Result) - 1); Delete(Result, 1, Pos(':', Result) - 1); Cells[3, RowCount - 1] := IntToStr(((KernelDay - 1) * 24) + StrToInt(strHours)) + Result; //Get the user time and format it FileTimeToSystemTime(lpUserTime, lpSystemTime); UserDay := lpSystemTime.wDay; UserTime := SystemTimeToDateTime(lpSystemTime); Result := TimeToStr(UserTime); strHours := Copy(Result, 1, Pos(':', Result) - 1); Delete(Result, 1, Pos(':', Result) - 1); Cells[4, RowCount - 1] := IntToStr(((UserDay - 1) * 24) + StrToInt(strHours)) + Result;//TimeToStr(UserTime); //Calculate the cpu time and format it Result := TimeToStr(UserTime + KernelTime); strHours := Copy(Result, 1, Pos(':', Result) - 1); Delete(Result, 1, Pos(':', Result) - 1); Cells[2, RowCount - 1] := IntToStr(((UserDay - KernelDay) * 24) + StrToInt(strHours)) + Result; finally CloseHandle(PH); end end; procedure TggProcessViewer.KillSelectedProcess; var PH : THandle; lpExitCode : DWord; hProcess : Cardinal; begin hProcess := StrToInt64(Cells[1, Row]); PH := OpenProcess(PROCESS_TERMINATE or PROCESS_QUERY_INFORMATION, FALSE, hProcess); if PH <> 0 then begin if GetExitCodeProcess(PH, lpExitCode) then begin if MessageBox(Handle, PChar('Do you really want me to try ' + 'to kill this process ?'), 'Please Confirm', MB_YESNO) = mrYES then begin TerminateProcess(PH, lpExitCode); MessageBox(Handle, PChar('should be dead now...'), PChar('Check it out...'), MB_OK); end; end else MessageBox(Handle, PChar('Could not retreive the ExitCode ' + 'for this process.' + #13 + #13 + SysErrorMessage(GetLastError)), PChar('Something went wrong...'), MB_OK); CloseHandle(PH); end else MessageBox(Handle, PChar('Could not get access to this process.' + #13 + #13 + SysErrorMessage(GetLastError)), PChar('Something went wrong...'), MB_OK); Refresh; end; procedure TggProcessViewer.Refresh; begin if assigned(FBeforeRefreshProcesses) and not (csLoading in ComponentState) then FBeforeRefreshProcesses(Self); GetProcesses; if assigned(FAfterRefreshProcesses) and not (csLoading in ComponentState) then FAfterRefreshProcesses(Self); end; function TggProcessViewer.SetProcessCount: integer; begin Result := FProcessCount; end; procedure TggProcessViewer.GetProcessCount(const Value: integer); begin FProcessCount := RowCount - 1; end; procedure TggProcessViewer.SetAutoRefresh(const Value: boolean); begin FAutoRefresh := Value; RefreshTimer.Enabled := FAutoRefresh; end; destructor TggProcessViewer.Destroy; begin FreeAndNil(RefreshTimer); inherited; end; procedure TggProcessViewer.TimerAutoRefresh(Sender: TObject); begin RefreshTimer.OnTimer := NIL; Refresh; RefreshTimer.OnTimer := TimerAutoRefresh; end; procedure TggProcessViewer.GetProcessesOnWinXX; var aHandle : THandle; FoundOne : bool; ProcessEntry32 : TProcessEntry32; ExeFile : string; J, ColBeforeRefresh : integer; PIDContentsBeforeRefresh : string; PriorityClass : DWord; begin ColBeforeRefresh := Col; PIDContentsBeforeRefresh := Cells[1, Row]; Perform(WM_SETREDRAW, 0, 0); try InitGridForWinXX; aHandle := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0); if aHandle <> 0 then try ProcessEntry32.dwSize := SizeOf(TProcessEntry32); FoundOne := Process32First(aHandle, ProcessEntry32); while FoundOne do begin ExeFile := ProcessEntry32.szExeFile; Cells[0, RowCount - 1] := ExtractFileName(ExeFile); Cells[1, RowCount - 1] := IntToStr(ProcessEntry32.th32ProcessID); PriorityClass := GetPriorityClass(ProcessEntry32.th32ProcessID); if PriorityClass <> 0 then case PriorityClass of HIGH_PRIORITY_CLASS: Cells[2, RowCount - 1] := 'High'; IDLE_PRIORITY_CLASS: Cells[2, RowCount - 1] := 'Idle'; NORMAL_PRIORITY_CLASS: Cells[2, RowCount - 1] := 'Normal'; REALTIME_PRIORITY_CLASS : Cells[2, RowCount - 1] := 'RealTime'; end else Cells[2, RowCount - 1] := IntToStr(ProcessEntry32.pcPriClassBase); Cells[3, RowCount - 1] := ExtractFilePath(ExeFile); RowCount := RowCount + 1; ProcessEntry32.dwSize := SizeOf(TProcessEntry32); FoundOne := Process32Next(aHandle, ProcessEntry32); end; finally CloseHandle(ahandle); end; if RowCount > 2 then RowCount := RowCount - 1; FProcessCount := RowCount - 1; for J := 1 to RowCount - 1 do if Cells[1, J] = PIDContentsBeforeRefresh then begin Col := ColBeforeRefresh; Row := J; Break; end; finally Perform(WM_SETREDRAW, 1, 0); Invalidate; end; end; procedure TggProcessViewer.Getprocesses; var HandlePSAPI_DLL : THandle; begin HandlePSAPI_DLL := LoadLibrary(cPSAPIDLL); if (HandlePSAPI_DLL <> 0) then //Where on NT/2000... begin @EnumProcesses := GetProcAddress(HandlePSAPI_DLL, 'EnumProcesses'); @GetModuleBaseNameA := GetProcAddress(HandlePSAPI_DLL, 'GetModuleBaseNameA'); @GetModuleFileNameExA := GetProcAddress(HandlePSAPI_DLL, 'GetModuleFileNameExA'); @EnumProcessModules := GetProcAddress(HandlePSAPI_DLL, 'EnumProcessModules'); GetProcessesOnNT; FreeLibrary(HandlePSAPI_DLL); end else //Where on Win95/98/ME GetProcessesOnWinXX; end; end.