Mucha gente ha inundado mi carpeta de emails pendientes preguntandome sobre el tema de este truco.
Se trata de lo siguiente: tomar una 'instantanea' de los programas que hay en ejecucion en un momento dado, y luego, cuando lo necesitemos, cerrar todos aquellos programas que se hayan abierto despues.
Por ejemplo, esto sería útil en un programa de control de acceso al ordenador: dejamos que el usuario haga lo que tenga que hacer, pero cuando termine, ejecutamos una funcion que nos cierre todos aquellos programas que el usuario despistado haya olvidado cerrar.
Antes de continuar, deciros que este truco está basado en los siguientes trucos:
[287] - Obtener una lista de los EXEs en ejecución
[290] - Cerrar una aplicacion sabiendo el nombre de su ejecutable
Bien, necesitamos varias cosas:
Una funcion que nos haga la instantanea de los programas en ejecucion, asi como un sitio donde guardarla
Y otra funcion que nos cierre aquellos programas que no estaban en la instantanea tomada anteriormente
Empecemos:
Primero, añadimos TlHelp32 en el uses de nuestra form
Ahora, declaramos esta variable en la parte private de la form:
private
{ Private declarations }
ProgramasAntes : TStringList;
|
se trata de la lista de programas que guardaremos....
Ahora, necesitamos crear y destruir esta lista para poder usarla. Lo haremos en los eventos OnCreate y OnDestroy de la form:
procedure TForm1.FormCreate(Sender: TObject);
begin
ProgramasAntes:=TStringList.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
ProgramasAntes.Free;
end;
|
Bien, ahora necesitamos la procedure que hará la "Instantanea" de los programas:
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;
|
Sin ilvidarnos de su declaracion en la parta private de la form:
procedure GuardaInstante(const Lista:TStringList);
|
Ahora, la procedure que "asesinara" a los programas que no estuvieran en la instantanea tomada con anterioridad:
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;
|
y su declaracion, claro:
procedure MataLosQueSobran(const Antes:TStringList);
|
Finalmente, nos falta la llamada que hay que hacer para tomar la "instantanea":
procedure TForm1.Button1Click(Sender: TObject);
begin
GuardaInstante(ProgramasAntes);
end;
|
y la que matara los programas que sobran:
procedure TForm1.Button2Click(Sender: TObject);
begin
MataLosQueSobran(ProgramasAntes);
end;
|
Para quitaros trabajo, aqui teneis la unit completa del ejemplo. Tendreis que poner dos botones en una form (Button1 y Button2) y pegar este codigo en la unit de la 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.
|
|