Program "Closer"  

Send By: Radikal (Q3 Team)
Web : http://www.q3.nu
Email: radikal@q3.nu
Date: 08/09/00

Tip accessed 802 times

 


A lot of people have flooded my folder of pending emails wondering on the topic of this tip.
It is the following thing: to take a ' snap-shot' of the programs that there is in execution in a given moment, and then, when we need it, to close all those programs that have opened up later.
For example, this would be useful in a program of access control to the computer: we let the user to make what has to make, but when he finishes, we execute a function that it closes us all those programs that the misled user has forgotten to close.
Before continuing, to tell you that this trick is based on the following tricks:

[287] - Obtain a list of the EXEs in execution
[290] - Close an application by it's executable name


Well, we need several things:
  • A function that makes us the snap-shot of the programs in execution, as well as a place where to keep it
  • And another function that it closes us those programs that were not in the snap-shot one taken previously

    Let us begin:

  • First, add TlHelp32 in the uses of your form

  • now, we declare this variable in the private part of the form:


       private
         { Private declarations }
         ProgramasAntes    : TStringList;
    



    it's the program list to store...

  • Now, we need crate and destroy this variable for we can use it. For example, in the OnCreate and OnDestroy events of the form:


     procedure TForm1.FormCreate(Sender: TObject);
     begin
       ProgramasAntes:=TStringList.Create;
     end;
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       ProgramasAntes.Free;
     end;
    



  • Well, now we need the procedure for make the snap-shot:



     procedure TForm1.GuardaInstante(const Lista:TStringList);
    
         function SacaExe(MangoW:HWND):string;
         {Obtiene el EXE de una tarea}
         {get EXE of a task}
         var
           Datos    :TProcessEntry32;
           hID       : DWord;
           Snap    : Integer;
         begin
           GetWindowThreadProcessId(MangoW,@hID);
           Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
           try
             Datos.dwSize:=SizeOf(Datos);
             if(Process32First(Snap,Datos))then
             begin
               repeat
                 if Datos.th32ProcessID=hID then
                 begin
                   Result:=UpperCase(StrPas(Datos.szExeFile));
                   Break;
                 end;
               until not(Process32Next(Snap,Datos));
             end;
           finally
             Windows.CloseHandle(Snap);
           end;
         end;
    
    
        function ObtieneVentanas(Mango: HWND;
                 Nada: Pointer): Boolean; stdcall;
        var
           sTemp:string;
        begin
          Result := True;
          {Mango es el handle de la tarea encontrada}
          {Añadimos el .EXE si no está ya añadido...}
          sTemp:=SacaExe(Mango);
           with TStringList(Nada) do
             if IndexOf(sTemp) = - 1 then Add(sTemp);
        end;
    
     begin
       Lista.Clear;
       EnumWindows( @ObtieneVentanas, Integer(Lista) );
     end;
    



    don't forget declare it in the private of the form:

         procedure GuardaInstante(const Lista:TStringList);
    



  • Now, the procedure that 'kill" the programs not found in the snap-shot (sorry for my english...)


     procedure TForm1.MataLosQueSobran(const Antes:TStringList);
     var
        i                : integer;
        ProgramasDespues : TStringList;
    
       procedure KillTask(FileName:String);
       var
           ContinueLoop:BOOL;
           FSnapshotHandle:THandle;
           FProcessEntry32:TProcessEntry32;
       const
           PROCESS_TERMINATE=$0001;
       begin
           FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
           FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
           ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32);
           while integer(ContinueLoop)<>0 do
           begin
               if FProcessEntry32.szExeFile=FileName then
                 TerminateProcess( OpenProcess(PROCESS_TERMINATE,BOOL(0),
                                   FProcessEntry32.th32ProcessID),0);
                 ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
           end;
           CloseHandle(FSnapshotHandle);
       end;
    
     begin
       ProgramasDespues:=TStringList.Create;
       try
         GuardaInstante(ProgramasDespues);
         for i:=0 to ProgramasDespues.Count-1 do
           If Antes.IndexOf( ProgramasDespues[i] ) = -1 then
             KillTask( ProgramasDespues[i] );
       finally
         ProgramasDespues.Free;
       end;
     end;
    


    and its declaration, of course:

         procedure MataLosQueSobran(const Antes:TStringList);
    



  • Finally, we lack the call that it is necessary to make to take the snap-shot one:


     procedure TForm1.Button1Click(Sender: TObject);
     begin
       GuardaInstante(ProgramasAntes);
     end;
    



    and the one that killed the programs that it have more than enough:


     procedure TForm1.Button2Click(Sender: TObject);
     begin
       MataLosQueSobran(ProgramasAntes);
     end;
    



    To take off I work, here you have the complete unit of the example. You will have to put two TButtons in a form (Button1 and Button2) and paste this code in the unit of the form:


     unit Unit1;
    
     interface
    
     uses
       Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
       TlHelp32, StdCtrls;
    
     type
       TForm1 = class(TForm)
         Button1: TButton;
         Button2: TButton;
         procedure Button1Click(Sender: TObject);
         procedure FormCreate(Sender: TObject);
         procedure FormDestroy(Sender: TObject);
         procedure Button2Click(Sender: TObject);
       private
         { Private declarations }
         ProgramasAntes    : TStringList;
         procedure GuardaInstante(const Lista:TStringList);
         procedure MataLosQueSobran(const Antes:TStringList);
       public
         { Public declarations }
       end;
    
     var
       Form1: TForm1;
    
     implementation
    
     {$R *.DFM}
    
     procedure TForm1.GuardaInstante(const Lista:TStringList);
    
         function SacaExe(MangoW:HWND):string;
         {Obtiene el EXE de una tarea}
         {get EXE of a task}
         var
           Datos    :TProcessEntry32;
           hID       : DWord;
           Snap    : Integer;
         begin
           GetWindowThreadProcessId(MangoW,@hID);
           Snap:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
           try
             Datos.dwSize:=SizeOf(Datos);
             if(Process32First(Snap,Datos))then
             begin
               repeat
                 if Datos.th32ProcessID=hID then
                 begin
                   Result:=UpperCase(StrPas(Datos.szExeFile));
                   Break;
                 end;
               until not(Process32Next(Snap,Datos));
             end;
           finally
             Windows.CloseHandle(Snap);
           end;
         end;
    
    
        function ObtieneVentanas(Mango: HWND;
                 Nada: Pointer): Boolean; stdcall;
        var
           sTemp:string;
        begin
          Result := True;
          {Mango es el handle de la tarea encontrada}
          {Añadimos el .EXE si no está ya añadido...}
          sTemp:=SacaExe(Mango);
           with TStringList(Nada) do
             if IndexOf(sTemp) = - 1 then Add(sTemp);
        end;
    
     begin
       Lista.Clear;
       EnumWindows( @ObtieneVentanas, Integer(Lista) );
     end;
    
     procedure TForm1.MataLosQueSobran(const Antes:TStringList);
     var
        i                : integer;
        ProgramasDespues : TStringList;
    
       procedure KillTask(FileName:String);
       var
           ContinueLoop:BOOL;
           FSnapshotHandle:THandle;
           FProcessEntry32:TProcessEntry32;
       const
           PROCESS_TERMINATE=$0001;
       begin
           FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
           FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
           ContinueLoop:=Process32First(FSnapshotHandle,FProcessEntry32);
           while integer(ContinueLoop)<>0 do
           begin
               if FProcessEntry32.szExeFile=FileName then
                 TerminateProcess( OpenProcess(PROCESS_TERMINATE,BOOL(0),
                                   FProcessEntry32.th32ProcessID),0);
                 ContinueLoop:=Process32Next(FSnapshotHandle,FProcessEntry32);
           end;
           CloseHandle(FSnapshotHandle);
       end;
    
     begin
       ProgramasDespues:=TStringList.Create;
       try
         GuardaInstante(ProgramasDespues);
         for i:=0 to ProgramasDespues.Count-1 do
           If Antes.IndexOf( ProgramasDespues[i] ) = -1 then
             KillTask( ProgramasDespues[i] );
       finally
         ProgramasDespues.Free;
       end;
     end;
    
     procedure TForm1.FormCreate(Sender: TObject);
     begin
       ProgramasAntes:=TStringList.Create;
     end;
    
     procedure TForm1.FormDestroy(Sender: TObject);
     begin
       ProgramasAntes.Free;
     end;
    
     procedure TForm1.Button1Click(Sender: TObject);
     begin
       GuardaInstante(ProgramasAntes);
     end;
    
    
     procedure TForm1.Button2Click(Sender: TObject);
     begin
       MataLosQueSobran(ProgramasAntes);
     end;
    
     end.