Detener procesos y servicios con Delphi


Resultado de imagen de imagen de cerrar procesos




Examinando los procesos que se estaban ejecutando en mi PC, me dí cuenta que muchos de ellos no servían para nada y lo único que hacían era consumir ciclos de CPU y tiempo de trabajo de disco duro, ocupaban memoria disponible y utilizaban internet para enviar y recibir datos, consumiendo un ancho de banda que es limitado.




Ya sé que desde el Administrador de tareas se pueden finalizar uno a uno, pero me dije ¿por qué no hacer un programa que me los finalice a todos pulsando un botón? y me puse a ello.




Pensé que lo mejor era dividirlo en dos módulos, uno sería un fichero de texto donde colocaría los nombres de los procesos y servicios y otro sería el programa en sí, de tal forma que cuando se iniciase haría lo siguiente:



1) Leer el fichero "ProcesosACerrar.txt"con los nombres de procesos y servicios línea a línea.

2) Después identificaría si es un programa o un servicio, leyendo el carácter que hay antes de la coma.

3) Por último lo detendría mediante la llamada al procedimiento StopProceso o StopService




El fichero "ProcesosACerrar.txt" sería por ejemplo como sigue:



S,Spooler

S,KinectManagement

S,igfxcuiservice1.0.0.0

S,AdobeARMservice

P,ACDaemon.exe

P,ACService.exe

P,jucheck.exe



A continuación os copio el ejecutable que he desarrollado.






USES
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, tlhelp32, winsvc;

// funciones del programa

FUNCTION TForm1.GetToken(Cadena, Separador: ansiSTRING; Token: Integer): ansiSTRING;
{
Cadena es el string en el que buscar el token
Separador es el string que separa cada token
Token es el número de token que buscamos
}
BEGIN
Cadena := Cadena + Separador;
WHILE Token > 1 DO
BEGIN
Delete(Cadena, 1, AnsiPos(Separador, Cadena));
Dec(Token);
END;
Result := Copy(Cadena, 1, AnsiPos(Separador, Cadena) - Length(Separador));
END;

PROCEDURE TForm1.Button10Click(Sender: TObject);
VAR
lista: tstringlist;
i: Integer;
linea, tipo, ProcesoOServicio, dato: STRING;
BEGIN
memo1.lines.clear;
IF FileExists('C:\ProcesosACerrar.txt', true) THEN
BEGIN
lista := tstringlist.CREATE;
TRY
lista.loadfromfile('C:\ProcesosACerrar.txt');
FOR i := 0 TO lista.Count - 1 DO
BEGIN
linea := trim(lista.strings[i]);
IF linea <> '' THEN
BEGIN
// linea es p.ej si es un proceso : P,notepad.exe
// linea es p.ej si es un servicio : S,spooler

tipo := GetToken(trim(lista.strings[i]), ',', 1);
//tipo puede ser P o S
ProcesoOServicio := GetToken(linea, ',', 2);
//ProcesoOServicio es el nombre del proceso o servicio
IF tipo = 'P' THEN
StopProceso(ProcesoOServicio);
IF tipo = 'S' THEN
StopService(ProcesoOServicio);
END;
END;
FINALLY
lista.free;
END;
END
ELSE
showmessage(' no se encuentra el archivo ' + 'C:\ProcesosACerrar.txt')
END;


PROCEDURE TForm1.StopService(nombre: STRING);
VAR
ServiceControlManager: SC_HANDLE;
Service: SC_HANDLE;
ServiceStatus: SERVICE_STATUS;
Resultado: boolean;
BEGIN
ServiceControlManager := OpenSCManager(NIL, NIL, SC_MANAGER_CONNECT);
IF ServiceControlManager <> 0 THEN
BEGIN
Service := OpenService(ServiceControlManager, PChar(nombre), SERVICE_ALL_ACCESS);
IF Service <> 0 THEN
BEGIN
IF QueryServiceStatus(Service, ServiceStatus) THEN
BEGIN
IF ServiceStatus.dwCurrentState <> SERVICE_STOPPED THEN
BEGIN
Resultado := ControlService(Service, SERVICE_CONTROL_STOP, ServiceStatus);
IF Resultado THEN
Memo1.lines.add('Servicio ' + nombre + ' detenido')
ELSE
Memo1.lines.add(' Error al parar el servicio ' + nombre);
END;
END;
CloseServiceHandle(Service);
END;
CloseServiceHandle(ServiceControlManager);
END;
END;


FUNCTION TForm1.StopProceso(nombre: STRING): boolean;
VAR
ModuleEntry: TModuleEntry32;
ProcessEntry: TProcessEntry32;
hSnapshot, hProcess: Cardinal;
BEGIN
Result := False;
ModuleEntry.dwSize := SizeOf(TModuleEntry32);
ProcessEntry.dwSize := SizeOf(TProcessEntry32);
hSnapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
IF Process32First(hSnapshot, ProcessEntry) THEN
REPEAT
IF (lstrcmpi(PChar(nombre), @ProcessEntry.szExeFile) = 0) THEN
BEGIN
hProcess := OpenProcess(PROCESS_TERMINATE, False, ProcessEntry.th32processid);
Result := TerminateProcess(hProcess, 0);
IF Result THEN
Memo1.lines.add(nombre + ' - ' + 'Cerrado')
ELSE
Memo1.lines.add(nombre + ' - ' + 'Error al cerrar.');

CloseHandle(hProcess);
END;
UNTIL NOT Process32Next(hSnapshot, ProcessEntry);
CloseHandle(hSnapshot);
END;



Después de haber ejecutado el programa si accedemos al Administrador de tareas de Windows se ve que el consumo de CPU, memoria, disco, ethernet ha disminuido, en mi caso he conseguido cerrar 30 procesos de los 68 que tenía, un 44% de recursos ociosos del sistema y la verdad es que se nota al trabajar con el PC, ahora parece que va "más ligero", las aplicaciones se abren antes y al navegar por internet me da la impresión que las páginas se abren más rápido.


Un detalle que hay que tener en cuenta, es que el ejecutable se debe iniciar como Administrador de la máquina (clic con el botón derecho sobre el programa y en el menú emergente activar el menú "Ejecutar como Administrador", ya que se necesita un usuario con los máximos privilegios para cerrar programas y servicios.




2 comentarios:

Simulación del movimiento de los electrones en un campo electrico

Espectacular simulación realizada con OpenGL del movimiento de los electrones cuando atraviesan un campo eléctrico. Como muestra la image...