Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Hook dll, votre avis m'intéresse

6 réponses
Avatar
Roger
Bonjour,
Quand je fais un hook dans une DLL, il y a un petit problème à résoudre au
niveau du programme principal qui lance la DLL. En effet, la fonction DLL
qui lance le HOOK revenant immédiatement dans le programme principal, il ne
faut pas que le programme principal se termine, sinon la DLL se termine
aussi, et le HOOK est perdu !
J'ai envisagé trois solutions pour bloquer le programme principal, sur les
3, les deux premières fonctionnent très bien et je voudrais savoir, à votre
avis, laquelle consomme le moins de ressources système et éventuellement si
vous connaissez d'autres solutions encore plus astucieuses pour arriver au
même résultat.

1ère solution qui marche: je fais une petit programme principal sans fenêtre
et après l'appel de la DLL, j'utilise la fonction API32: Sleep(INFINITE);

2ème solution qui marche: je fais un programme principal avec une fenêtre
(éventuellement invisible) et après l'appel de la DLL, le programme
principal reste bloqué sur sa boucle: Getmessage();

3ème solution qui ne marche pas: je fais un programme principal sans
fenêtre, je m'arrange pour que l'appel de la fonction qui lance la DLL me
transmette en retour le handle du HOOK, puis après le retour de la fonction
DLL et toujours dans le programme principal, j'utilise la fonction API32:
WaitForSingleObjectEx(hookdll, INFINITE, false);
qui est sensée bloquer sur le non changement d'état de n'importe quel objet,
mais qui visiblement ne bloque pas pour ce type d'objet.

Votre avis m'intéresse.
Merci

6 réponses

Avatar
Christian ASTOR
Roger a écrit :

2ème solution qui marche: je fais un programme principal avec une fenêtre
(éventuellement invisible) et après l'appel de la DLL, le programme
principal reste bloqué sur sa boucle: Getmessage();



C'est ce qu'il faut faire, un simple prog Win32 "windowless" (sans fenêtre)
Mais tu n'es pas obligé d'utiliser une DLL
Tu peux utiliser les Low Level Hooks

Un exemple tout bête sans DLL, qui bloque les touches Windows et Beep()
pour tester sur VK_LCONTROL =>

#include <windows.h>
#include <tchar.h>

HINSTANCE hInst;
HHOOK hKeyboardHook;
LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam);

int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc,
hInstance, 0);
Beep(200, 200);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
}


LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM
lParam)
{
DWORD dwKey = 0;
if (lParam)
{
KBDLLHOOKSTRUCT *pkbdll = (KBDLLHOOKSTRUCT*)lParam;
dwKey = pkbdll->vkCode;
if (dwKey == VK_LCONTROL)
Beep(1500, 100);
else if (dwKey == VK_RWIN || dwKey == VK_LWIN) // Windows key
return 1;
if (dwKey == VK_F11)
{
Beep(500, 100);
UnhookWindowsHookEx(hKeyboardHook);
PostQuitMessage(0);
}
}
return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam);
}
Avatar
Roger
Ton exemple est intéressant et je t'en remercie, d'autant que le low level
hook n'était pas documenté dans ma doc qui doit être assez ancienne.
Cependant j'ai testé et le compilateur prend quand même le « -LL ».

Mais ça n'était pas exactement l'objet de ma question, car ton exemple, il
est quelque part équivalent à ma solution 2 pour ce qui concerne l'attente
de la fin du hook, ton programme attend la fin du hook sur une boucle
GetMessage(...).

Ma question était : en considérant que le fonctionnement est celui-ci :

Une dll contient une fonction qui ne fait que lancer le hook et qui retourne
immédiatement dans le programme principal. Cette dll contient aussi la
callback du traitement des évènements (touches) piégés par le hook.

Donc quand le programme principal lance la fonction ci-dessus de la dll, la
fonction dll lance le hook et rend immédiatement la main au programme
principal et en parallèle le traitement des touches va se dérouler dans la
dll indépendamment du programme principal à condition cependant qu'après
avoir récupéré la main le programme principal ne se termine pas.

Ma question portait donc sur ce que le programme principal doit faire après
avoir récupéré la main de la fonction dll : est-ce qu'il vaut mieux qu'il
attende sur une boucle GetMessage(.) ce qui correspond à ma solution 2 ou à
ton exemple (à ceci près que toi c'est sans dll), ou est ce que pour
consommer moins de ressources système il vaut mieux qu'il attende sur une
fonction Sleep(INFINITE).

J'ai les deux versions et elles marchent toutes les deux (ma version avec
Sleep ne comporte évidemment aucune boucle GetMessage).

J'avais aussi une question subsidiaire (mais c'est pour ma culture
personnelle), est-ce qu'il existe d'autres solutions d'attente encore moins
onéreuses ?

PS. Je n'ai pas testé, mais il est possible que dans ton exemple aussi tu
puisses remplacer ta boucle GetMessage(...) par un simple Sleep(INFINITE);

A+
Avatar
Christian ASTOR
Roger a écrit :

Mais ça n'était pas exactement l'objet de ma question, car ton exemple, il
est quelque part équivalent à ma solution 2 pour ce qui concerne l'attente
de la fin du hook, ton programme attend la fin du hook sur une boucle
GetMessage(...).

Ma question était : en considérant que le fonctionnement est celui-ci :



Ben si, c'est ce que j'ai répondu en préambule :
"
C'est ce qu'il faut faire, un simple prog Win32 "windowless" (sans fenêtre)
"
Avatar
Roger
Ben si, c'est ce que j'ai répondu en préambule :
"
C'est ce qu'il faut faire, un simple prog Win32 "windowless" (sans
fenêtre)



Excuse-moi, je n'avais pas compris que tu voulais dire que de ton point de
vue la boucle GetMessage(...) consommait moins de temps UC que un simple
Sleep(INFINITE).
Initialement j'avais imaginé le contraire car je pensais que ces deux
instructions fonctionnaient sur micro, comme sur les gros ordinateurs sur
lesquels, il y a longtemps, je deboggais le système: les instructions du
type sleep ne prenaient aucun temps UC puisque c'était un timer hardware
externe à l'UC qui était armé pour la durée du sleep et qui envoyait une
interruption hardware externe sur l'UC lorsqu'il déclenchait (l'UC n'était
donc sollicitée que 2 fois: la première pour l'armement du timer hardware,
la 2ème à son déclenchement pour reprendre la main), tandis que les boucles
du type Getmessage sollicitaient en permanence l'UC pour aller voir s'il y
avait un message dans sa file à traiter et ceci pendant tout le temps
d'attente de fin du programme.
Mais je comprends que tu me dis que sur les micros que je connais beaucoup
moins bien, ça ne fonctionne pas pareil.
Cordialement,
Merci.
Avatar
Christian ASTOR
Roger a écrit :
Ben si, c'est ce que j'ai répondu en préambule :
"
C'est ce qu'il faut faire, un simple prog Win32 "windowless" (sans
fenêtre)



Excuse-moi, je n'avais pas compris que tu voulais dire que de ton point de
vue la boucle GetMessage(...) consommait moins de temps UC que un simple
Sleep(INFINITE).
Initialement j'avais imaginé le contraire car je pensais que ces deux
instructions fonctionnaient sur micro, comme sur les gros ordinateurs sur
lesquels, il y a longtemps, je deboggais le système: les instructions du
type sleep ne prenaient aucun temps UC puisque c'était un timer hardware
externe à l'UC qui était armé pour la durée du sleep et qui envoyait une
interruption hardware externe sur l'UC lorsqu'il déclenchait (l'UC n'était
donc sollicitée que 2 fois: la première pour l'armement du timer hardware,
la 2ème à son déclenchement pour reprendre la main), tandis que les boucles
du type Getmessage sollicitaient en permanence l'UC pour aller voir s'il y
avait un message dans sa file à traiter et ceci pendant tout le temps
d'attente de fin du programme.
Mais je comprends que tu me dis que sur les micros que je connais beaucoup
moins bien, ça ne fonctionne pas pareil.
Cordialement,
Merci.



Non, non, tu as parfaitement raison !
Sleep() ne prends pas de temps, tout comme un WaitForSingleObject() sur
un event (CreateEvent(), ...)
Mais je voulais dire que pour lancer un hook, c'est ce qu'on utilise de
façon habituelle...
Avatar
Roger

Non, non, tu as parfaitement raison !
Sleep() ne prends pas de temps, tout comme un WaitForSingleObject() sur un
event (CreateEvent(), ...)
Mais je voulais dire que pour lancer un hook, c'est ce qu'on utilise de
façon habituelle...




OK thanks
A+