2010-07-02 34 views
3

Comment décharger correctement une DLL de tous les processus lorsque le hook qui les a chargés est déchargé?Déchargement de la DLL de tous les processus après le décrochage du hook global CBT

De MSDN:

Vous pouvez libérer une procédure crochet global en utilisant UnhookWindowsHookEx, mais cette fonction ne libère pas la DLL contenant la procédure de crochet . Cela est dû au fait que les procédures de hook globales sont appelées dans le contexte de processus de chaque application sur le bureau, entraînant un appel implicite à la fonction LoadLibrary pour tous ces processus. Parce qu'un appel à la fonction FreeLibrary ne peut pas être effectué pour un autre processus, il est puis aucun moyen de libérer la DLL. Le système libère éventuellement la DLL après tous les processus explicitement liés à la DLL ont soit terminé ou appelé FreeLibrary et tous les processus qui méthode dite de la crochet ont repris le traitement en dehors de la DLL.

Ce que je cherche, est une méthode pour détecter lorsque le crochet est décrocha, puis appelez FreeLibrary de tous les processus qui ont été accrochés. Existe-t-il d'autres moyens pour provoquer le déchargement instantané d'une DLL lorsque le hook est déchargé?

Répondre

1

En général, vous devez utiliser l'accrochage des fenêtres globales si FreeLibrary n'est pas requis. Si vous voulez faire cela, vous pouvez utiliser l'injection de DLL (voir par exemple http://www.codeproject.com/KB/threads/winspy.aspx et http://www.codeproject.com/KB/system/hooksys.aspx) par rapport à la technique CreateRemoteThread et LoadLibrary. Dans le cas, vous pouvez faire ce que vous voulez dans le processus à distance. Vous pouvez combiner les deux techniques.

Si vous souhaitez appeler FreeLibrary uniquement pour faire une mise à jour de la DLL, vous pouvez le faire d'une autre manière. Chaque DLL qui est chargée peut être renommée (dans cmd.exe par exemple) en un nom temporaire et vous pouvez appeler MoveFileEx avec le drapeau MOVEFILE_DELAY_UNTIL_REBOOT. Ensuite, vous pouvez déjà copier et utiliser une nouvelle version de la DLL. L'ancienne DLL sera supprimée au prochain redémarrage de l'ordinateur.

+1

Voulez-vous dire qu'une DLL déjà chargée peut être renommée à la volée? Ou que ma nouvelle version d'une DLL devrait prendre la place de l'ancienne seulement après un redémarrage? –

+0

Oui, toute DLL chargée peut être renommée à la volée. Essayez juste ceci. C'est un truc très ancien existant depuis Windows NT 3.1. Certaines installations modernes comme Windows Installer l'ont utilisé d'ailleurs. Vous avez dans la plupart des cas un avantage si vous déplacez et renommez l'ancienne DLL (qui peut être utilisée) dans un répertoire temporaire avec le nom temporaire et copiez une nouvelle version de DLL dans le nouvel emplacement. Les programmes qui ont chargé l'ancienne DLL peuvent continuer à fonctionner, mais vous pouvez utiliser une nouvelle DLL sans attendre le redémarrage.Le seul problème qui peut exister si vous avez beaucoup de DLL qui peut être chargé dynamiquement et dans le cas où vous pouvez avoir un mélange de DLL – Oleg

+0

Pourriez-vous expliquer pourquoi vous avez besoin de décharger la DLL dans votre cas? – Oleg

4

Hook dll sont déchargés dans leur boucle de message. Les forcer à passer dans la boucle des messages aide à les décharger.

Ajouter ce après votre UnhookWindowsHookEx pour forcer tous les messages boucles à se réveiller:

DWORD dwResult; 
SendMessageTimeout(HWND_BROADCAST, WM_NULL, 0, 0, SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 1000, &dwResult); 

Cependant, j'ai encore la question de temps en temps. Je ne sais pas d'où ça vient. Je suppose qu'un processus verrouillé pourrait empêcher la DLL de décharger, mais je n'ai aucune preuve de cela.