Capter l'ouverture de processus.

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 15 mai 2006 à 20:16
violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 - 15 mai 2006 à 21:30
Violent Ken
Salut à tous ! J'ai un problème assez complexe... Je le poste, merci à vous si vous pouvez m'aider !

Je suis en train de programmer un logiciel qui capte l'ouvertures de nouveaux processus Windows.
Voici les contraintes du cahier des charges sur ce point précis :
-le programme doit être capable de détecter TRES rapidement l'ouverture d'un processus (bien avant que la fenêtre de celui ci s'affiche)
-le programme ne doit PAS consommer de CPU (pas au dela de 1% du CPU d'un P4 3GHZ)
-le pogramme doit pouvoir trourner en tache de fond sans gêner le fonctionnement du PC
-le programme doit pouvoir détecter TOUT les nouveaux processus lancés
-le programme doi renvoyer le NUMERO de PID des nouveaux processus ouverts, et cela en ouvrant une form spécifique (une nouvelle form à chaque fois, grâce aux commandes
Dim Frm As Form
Set Frm = New frmAlert
Frm.lblPID.Caption = NewSuspectPID
Frm.Show)

Le seul problème rencontré dans la programmation des routines est le "captage" des nouveaux processus ouverts. Pour cela, j'utilise une méthode gravement impropre qui ne répond pas au deux premiers critères du CDCF : le programme met trop de temps pour capter l'ouverture d'un processus, et le programme consomme entre 3 et 6% de mon UC de manière constante.

Voici la méthode que j'ai utilisée actuellement pour mon programme (très impropre)
-timer réglé sur 200ms
-énumération des PID de tout les processus à chaque exécution du code du timer (toutes les 200ms) grâce au WMI
-détermination de la somme de tout les PID
-comparaison de la différence de somme de tout les PID entre 2 boucles de timer (si la somme est 45120 à la n-ième exécution du timer, et la somme est 46240 à la n+1-ième boucle, alors le processus de PID 46240-45120=1120 a été ouverts)

Problèmes :
-gourmand en CPU (boucle générée sans cesse toutes les 200ms ==> 5 à 6% d'UC consommée)
-pas assez rapide (retard de maximum 199ms si le processus est lancé au mauvais moment)
-bug quand plusieurs processus se ferment/ouvrent dans une intervalle de 200ms.

L'idéal serait donc de programmer un évenement qui détecte l'ouverture d'un nouveau processus, ou encore, de "capter" cette ouverture d'une autre manière (comment, par exemple, procède taskmgr.exe pour le faire ??)
Je ne sais pas si c'est possible vraiment, je sais juste que j'ai trouvé une source sur http://www.planet-source-code.com/ qui réalise cette tâche de manière plus efficace, en étant moins gourmand pour le processeur (entre 0 et 2% consommé pendant une phase de détection, c'est ce que je cherche)
Malheureusement, ce n'est absolument pas commenté et je ne comprend pas la méthode employée -_-
(disponible ici : http://www.planet-source-code.com/vb/scripts/ShowCode.asp?txtCodeId=59427&lngWId=1 )

Auriez vous des idées pour mon problème ? Comment capter de manière efficace TOUT les nouveaux processus (et accessoirement ceux qui se ferment, c'est optionnel ;)) en ne consommant qu'un MINIMUM de CPU ?
Merci énormément par avance !
Merci, @+ (Windows XP Ed familiale/Pro, VB6)

1 réponse

violent_ken Messages postés 1812 Date d'inscription mardi 31 mai 2005 Statut Membre Dernière intervention 26 octobre 2010 2
15 mai 2006 à 21:30
Violent Ken
Je suis tombé sur un code (en bas) et l'ai adapté : la consommation est largement moindre qu'avec WMI. C'est déjà une bonne chose (0-1-2% avec un timer de 1).
Le problème est donc a moitié résolu : le timer que j'utilise et qui lance ProcessList tout les centièmes de secondes me semble relativement malpropre. N'y aurais t-il pas moyen de "capter" réellement l'apparition d'un processus, et ce, sans boucle tournant en permanence ?
Créer un évênement captant l'ouverture d'un processus et renvoyant son PID, c'est vraiment çà que j'aimerais. Possible ou pas ? Si oui, des idées ? Merci beaucoup d'avance, et voici le code dont je parle :

Option Explicit
Dim a As Long, b As Long
Declare Function ProcessFirst Lib "kernel32" Alias "Process32First" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Declare Function ProcessNext Lib "kernel32" Alias "Process32Next" (ByVal hSnapshot As Long, uProcess As PROCESSENTRY32) As Long
Declare Function CreateToolhelpSnapshot Lib "kernel32" Alias "CreateToolhelp32Snapshot" (ByVal lFlags As Long, lProcessID As Long) As Long
Public Const MAX_PATH As Integer = 260
Public Const TH32CS_SNAPPROCESS As Long = 2&
Type PROCESSENTRY32
dwSize As Long
cntUsage As Long
th32ProcessID As Long
th32DefaultHeapID As Long
th32ModuleID As Long
cntThreads As Long
th32ParentProcessID As Long
pcPriClassBase As Long
dwFlags As Long
szexeFile As String * MAX_PATH
End Type

Public Function ProcessList()
Dim hSnapshot As Long
Dim uProcess As PROCESSENTRY32
Dim r As Long
hSnapshot = CreateToolhelpSnapshot(TH32CS_SNAPPROCESS, 0&)
If hSnapshot = 0 Then Exit Function
uProcess.dwSize = Len(uProcess)
r = ProcessFirst(hSnapshot, uProcess)
b = a
a = 0
Do While r
a = a + uProcess.th32ProcessID
r = ProcessNext(hSnapshot, uProcess)
Loop
If Not (b = a) And b > 0 Then MsgBox Abs(b - a)
End Function

Merci encore à tous pour cet excellent site. Bravo encore.
@+
0
Rejoignez-nous