ProcessNotify.pas
上传用户:rickyhu
上传日期:2007-05-27
资源大小:842k
文件大小:10k
源码类别:

控制台编程

开发平台:

Delphi

  1. unit ProcessNotify;
  2. interface
  3. uses
  4.   Windows, SysUtils, Classes, TLHelp32, PSApi;
  5. type
  6.    EProcessNotifyError = class(Exception);
  7.    TProcessNotifyEvent = procedure(Sender :TObject; const ProcessInfo :TProcessEntry32)
  8.       of object;
  9.    TOnProcessCreated   = procedure(StrInfo:string) of Object;
  10.    TOnProcessTerminated= procedure(StrInfo:string) of Object;
  11.    TProcessNotify = class(TComponent)
  12.    private
  13.       FPollInterval  :Integer;
  14.       FPollThread    :TThread;
  15.       FAsyncNotify   :Boolean;
  16.       FEnabled       :Boolean;
  17.       FOnProcessCreated:TOnProcessCreated;
  18.       FOnProcessTerminated:TOnProcessTerminated;
  19.       procedure SetPollInterval(Value :Integer);
  20.       function GetPollPriority :TThreadPriority;
  21.       procedure SetPollPriority(Value :TThreadPriority);
  22.       procedure SetEnabled(Value :Boolean);
  23.    protected
  24.       procedure Loaded; override;
  25.       procedure ProcessCreated(const ProcessInfo :TProcessEntry32); virtual;
  26.       procedure ProcessTerminated(const ProcessInfo :TProcessEntry32); virtual;
  27.    public
  28.       constructor Create(Aowner :TComponent); override;
  29.       destructor Destroy; override;
  30.    published
  31.       property AsyncNotify :Boolean
  32.          read FAsyncNotify write FAsyncNotify;
  33.       property Enabled :Boolean
  34.          read FEnabled write SetEnabled;
  35.       property PollInterval :Integer
  36.          read FPollInterval write SetPollInterval;
  37.       property PollPriority :TThreadPriority
  38.          read GetPollPriority write SetPollPriority;
  39.       property OnProcessCreated     :TOnProcessCreated
  40.         read FOnProcessCreated write FOnProcessCreated;
  41.       property OnProcessTerminated  :TOnProcessTerminated
  42.         read FOnProcessTerminated write FOnProcessTerminated;
  43.    end;
  44. implementation
  45. type
  46.    TProcessList = class(TList)
  47.    private
  48.       function GetEntries(Index :Integer):TPROCESSENTRY32;
  49.       function GetIndexOfProcessID(ID :THandle):Integer;
  50.       function GetProcessIDs(Index :Integer):Integer;
  51.       function GetTags(Index :Integer):Integer;
  52.       procedure SetTags(Index, Value :Integer);
  53.    protected
  54.       procedure ValidateIndex(Index :Integer);
  55.    public
  56.       destructor Destroy; override;
  57.       procedure DeleteEntry(Index :Integer);
  58.       procedure AddEntry(const AEntry :TPROCESSENTRY32);
  59.       property Entries[Index :Integer] :TPROCESSENTRY32
  60.          read GetEntries;
  61.       property ProcessIDs[Index :Integer] :Integer
  62.          read GetProcessIDs;
  63.       property IndexOfProcessID[ID :cardinal] :Integer
  64.          read GetIndexOfProcessID;
  65.       property Tags[Index :Integer] :Integer
  66.          read GetTags write SetTags;
  67.    end;
  68.    TPollThread = class(TThread)
  69.    private
  70.       FOwner :TProcessNotify;
  71.       FProcessList :TProcessList;
  72.       FEntry       :TProcessEntry32;
  73.       procedure DoProcessCreated;
  74.       procedure DoProcessTerminated;
  75.    protected
  76.       procedure Execute; override;
  77.       procedure DoTerminate; override;
  78.    public
  79.       constructor Create(AOwner :TProcessNotify);
  80.    end;
  81. const
  82.    sErrInvalidInterval      = 'Invalid poll interval value';
  83.    sErrIndexOutOfBounds     = 'Index out of bounds';
  84. { TPollThread }
  85. procedure TPollThread.DoProcessCreated;
  86. begin
  87.    FOwner.ProcessCreated(FEntry);
  88. end;
  89. procedure TPollThread.DoProcessTerminated;
  90. begin
  91.    FOwner.ProcessTerminated(FEntry);
  92. end;
  93. procedure TPollThread.Execute;
  94. var
  95.    S:THandle;
  96.    I:Integer;
  97.    R:Bool;
  98. begin
  99.    while not Terminated do
  100.       with FProcessList do
  101.       begin
  102.          //sleep(FOwner.FPollInterval);
  103.          sleep(1);
  104.          for I := 0 to Count-1 do Tags[I] := 0;
  105.          S := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  106.          if S <> -1 then
  107.          try
  108.             FEntry.dwSize := sizeof(FEntry);
  109.             R := Process32First(S, FEntry);
  110.             while R do
  111.             begin
  112.                I := IndexOfProcessID[FEntry.th32ProcessID];
  113.                if I < 0 then
  114.                begin
  115.                   AddEntry(FEntry);
  116.                   Tags[FProcessList.Count-1] := 1;
  117.                   if FOwner.FAsyncNotify then
  118.                      FOwner.ProcessCreated(FEntry)
  119.                   else
  120.                      Synchronize(DoProcessCreated);
  121.                end
  122.                else
  123.                   Tags[I] := 1;
  124.                FEntry.dwSize := sizeof(FEntry);
  125.                R := Process32Next(S, FEntry);
  126.             end;
  127.          finally
  128.             CloseHandle(S);
  129.          end;
  130.          for I := Count-1 downto 0 do
  131.          begin
  132.             if Tags[I] = 0 then
  133.             begin
  134.                FEntry := Entries[I];
  135.                if FOwner.FAsyncNotify then
  136.                   FOwner.ProcessTerminated(FEntry)
  137.                else
  138.                   Synchronize(DoProcessTerminated);
  139.                DeleteEntry(I);
  140.             end;
  141.          end;
  142.    end;
  143. end;
  144. constructor TPollThread.Create(AOwner :TProcessNotify);
  145. var
  146.    S :Thandle;
  147.    R :Bool;
  148. begin
  149.    assert(assigned(AOwner));
  150.    inherited Create(true);
  151.    FOwner := AOwner;
  152.    S := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  153.    try
  154.       FEntry.dwSize := sizeof(FEntry);
  155.       FProcessList := TProcessList.Create;
  156.       R := Process32First(S, FEntry);
  157.       while R do
  158.       with FProcessList do
  159.       begin
  160.          AddEntry(FEntry);
  161.          Tags[Count-1] := 0;
  162.          R := Process32Next(S, FEntry);
  163.       end;
  164.    finally
  165.       CloseHandle(S);
  166.    end;
  167. end;
  168. procedure TPollThread.DoTerminate;
  169. begin
  170.    inherited DoTerminate;
  171.    if FProcessList <> Nil then
  172.       FProcessList.Free;
  173. end;
  174. { TProcessList }
  175. function TProcessList.GetTags(Index :Integer):Integer;
  176. begin
  177.    ValidateIndex(Index);
  178.    result := Entries[Index].dwSize;
  179. end;
  180. procedure TProcessList.SetTags(Index, Value :Integer);
  181. begin
  182.    ValidateIndex(Index);
  183.    PProcessEntry32(Items[Index])^.dwSize := Value;
  184. end;
  185. procedure TProcessList.ValidateIndex(Index :Integer);
  186. begin
  187.    if( Index < 0 ) or ( Index >= Count ) then
  188.       raise EListError.Create(sErrIndexOutOfBounds);
  189. end;
  190. function TProcessList.GetEntries(Index :Integer):TPROCESSENTRY32;
  191. begin
  192.    ValidateIndex(Index);
  193.    Result := PProcessEntry32(Items[Index])^;
  194. end;
  195. destructor TProcessList.Destroy;
  196. var
  197.    I :Integer;
  198. begin
  199.    for I := 0 to Count-1 do
  200.    begin
  201.       if Items[I] <> Nil then
  202.          FreeMem(Items[I]);
  203.    end;
  204.    inherited Destroy;
  205. end;
  206. procedure TProcessList.DeleteEntry(Index :Integer);
  207. begin
  208.    ValidateIndex(Index);
  209.    FreeMem(Items[Index]);
  210.    Delete(Index);
  211. end;
  212. procedure TProcessList.AddEntry(const AEntry :TPROCESSENTRY32);
  213. var
  214.    lpEntry :PPROCESSENTRY32;
  215. begin
  216.    GetMem(lpEntry, sizeof(TPROCESSENTRY32));
  217.    try
  218.       system.move(AEntry, lpEntry^, sizeof(AEntry));
  219.       Add(lpEntry);
  220.    except
  221.       FreeMem(lpEntry);
  222.       raise;
  223.    end;
  224. end;
  225. function TProcessList.GetIndexOfProcessID(ID :cardinal):Integer;
  226. var
  227.    I :Integer;
  228. begin
  229.    result := -1;
  230.    for I := 0 to Count-1 do
  231.    begin
  232.       if PProcessEntry32(Items[I])^.th32ProcessID = ID then
  233.       begin
  234.          result := I;
  235.          break;
  236.       end;
  237.    end;
  238. end;
  239. function TProcessList.GetProcessIDs(Index :Integer):Integer;
  240. begin
  241.    ValidateIndex(Index);
  242.    result := PProcessEntry32(Items[Index])^.th32ProcessID;
  243. end;
  244. { TProcessNotify }
  245. procedure TProcessNotify.SetPollInterval(Value :Integer);
  246. begin
  247.    if Value <> FPollInterval then
  248.    begin
  249.       if value < 0 then
  250.          raise EProcessNotifyError.Create(sErrInvalidInterval);
  251.       FPollInterval := Value;
  252.    end;
  253. end;
  254. procedure TProcessNotify.SetPollPriority(Value :TThreadPriority);
  255. begin
  256.    assert(assigned(FPollThread));
  257.    if Value <> PollPriority then
  258.       FPollThread.Priority := Value;
  259. end;
  260. procedure TProcessNotify.SetEnabled(Value :Boolean);
  261. begin
  262.    assert(assigned(FPollThread));
  263.    if Value <> Enabled then
  264.    begin
  265.       FEnabled := Value;
  266.       if not ((csLoading in ComponentState) or (csDesigning in COmponentState)) then
  267.          FPollThread.Suspended := not Value;
  268.    end;
  269. end;
  270. function TProcessNotify.GetPollPriority :TThreadPriority;
  271. begin
  272.    assert(assigned(FPollThread));
  273.    result := FPollThread.Priority;
  274. end;
  275. procedure TProcessNotify.Loaded;
  276. begin
  277.    inherited Loaded;
  278.    if not (csDesigning in ComponentState) then
  279.       FPollThread.Suspended := not FEnabled;
  280. end;
  281. constructor TProcessNotify.Create(Aowner :TComponent);
  282. begin
  283.    inherited Create(AOwner);
  284.    FPollThread := TPollThread.Create(Self);
  285. end;
  286. destructor TProcessNotify.Destroy;
  287. begin
  288.    if assigned(FPollThread) then
  289.       FPollThread.Free;
  290.    inherited Destroy;
  291. end;
  292. procedure TProcessNotify.ProcessCreated(const ProcessInfo :TProcessEntry32);
  293. var 
  294.    StrInfo:String;
  295.    FileName:array [0..MAX_PATH] of Char;
  296.    hProcess:THandle;
  297. begin
  298.   if assigned(FOnProcessCreated) then
  299.   begin
  300.     StrInfo:='20|'+IntToHex(ProcessInfo.th32ProcessID,4)+'|';
  301.     
  302.     hProcess:=OpenProcess(PROCESS_ALL_ACCESS or PROCESS_QUERY_INFORMATION ,
  303.                           FALSE,ProcessInfo.th32ProcessID);
  304.     if(hProcess>0) then
  305.     begin
  306.       if(GetModuleFileNameEx(hProcess,0,FileName,MAX_PATH)>0) then
  307.         StrInfo:=StrInfo+FileName+'|'
  308.       else
  309.         StrInfo:=StrInfo+ProcessInfo.szExeFile+'|';
  310.     end;
  311.     CloseHandle(hProcess);
  312.     //GetWindowText(ProcessInfo.th32ProcessID,FileName,MAX_PATH);
  313.     //StrInfo:=StrInfo+FileName;
  314.     FOnProcessCreated(StrInfo);
  315.   end;
  316. end;
  317. procedure TProcessNotify.ProcessTerminated(const ProcessInfo :TProcessEntry32);
  318. var 
  319.    StrInfo:String;
  320. begin
  321.    if assigned(FOnProcessTerminated) then
  322.    begin
  323.       StrInfo:='21|'+IntToHex(ProcessInfo.th32ProcessID,4)+'|';
  324.       StrInfo:=StrInfo+ProcessInfo.szExeFile;
  325.       FOnProcessTerminated(StrInfo);
  326.    end;
  327. end;
  328. end.