2010-08-04 10 views
2

Est-il possible pour une fonction qui est dans une DLL de décharger la DLL? Je dois faire ceci pour que je puisse m'assurer que la DLL n'est pas utilisée, puis écrire dans le fichier de la DLL.Déchargement DLL lui-même

Répondre

2

Je ne pense pas que cela fonctionnera. Appeler FreeLibrary avec un handle de l'extérieur (LoadLibrary aurait été appelé depuis une zone en dehors de la DLL) car le code s'exécute dans un emplacement de mémoire qui ne sera plus valide.

Même si cela est possible, ça sent mauvais. Peut-être que vous voulez faire une mise à jour ou similaire. Expliquez un peu plus quel est le résultat auquel vous vous attendez. Décharger une DLL de l'intérieur n'est pas la solution.

+1

Veuillez voir ma réponse concernant la fonction FreeLibraryAndExitThread –

+0

L'appel de FreeLibrary n'est pas la meilleure option si vous avez un thread d'arrière-plan dans votre DLL. Il est préférable d'utiliser [FreeLibraryAndExitThread] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms683153 (v = vs.85) .aspx). Cette fonction est une pierre qui peut tuer 2 oiseaux. –

0

Si vous demandez si vous pouvez décharger/désinstaller en toute sécurité une DLL chargée dans un processus à partir d'un code dans la DLL elle-même, la réponse est non - il n'y a pas de moyen sûr de le faire. Pensez-y de cette façon: Décharger une DLL est fait en décrémentant son compte de référence en utilisant FreeLibrary(). Le problème est bien sûr qu'une fois que le nombre de références de la DLL atteint zéro, le module est démappé. Ce qui signifie que le code dans la DLL qui a appelé FreeLibrary() est parti.

Même si vous pouviez le faire, vous devez toujours vous assurer qu'il n'y a aucun autre thread exécutant des fonctions exportées depuis la DLL.

4

Utilisez cette option lorsque le dll a fait travail:

CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)FreeLibrary, &__ImageBase, 0, NULL); 
    // terminate if dll run in a separate thread ExitThread(0); 
    // or just return out the dll 

Et le __ImageBase est la structure d'en-tête de PE de votre dll:

EXTERN_C IMAGE_DOS_HEADER __ImageBase; 
+0

Cette astuce peut aider, mais théoriquement, elle peut toujours conduire à une condition de concurrence si le thread appelant CreateThread reste trop longtemps après l'appel à CreateThread. S'il vous plaît voir ma réponse concernant la fonction FreeLibraryAndExitThread. –

11

Si je comprends bien, il peut être fait et est MEANT à faire parfois (par exemple en cas d'injection dll par CreateRemoteThread et d'autres méthodes). Donc,

FreeLibraryAndExitThread(hModule, 0) 

fera précisément cela.

D'autre part, appelant

FreeLibrary(hModule) 

ne fera pas ici - de MSDN. « Si elles devaient appeler FreeLibrary et ExitThread séparément, une condition de course existerait La bibliothèque pourrait être déchargé avant ExitThread est appelé." À titre de remarque, ExitThread fait de la comptabilité en plus de revenir de la fonction de thread.

Tout cela suppose que votre dll a obtenu le hModule lui-même en appelant LoadLibrary à l'intérieur du dll chargé, ou plutôt, en appelant à l'intérieur du dll chargé de la fonction suivante:

GetModuleHandleEx 
(
    GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, 
    (LPCTSTR)DllMain, 
    &hModule 
) 

Ce incrémente la référence compte de la Dll donc vous savez que si vous libérez la librairie plus tard en utilisant ce descripteur et si la librairie est vraiment déchargée alors vous avez eu la dernière référence.
Si vous sautez à la place incrémenter le compteur de références dll et obtenir le hModule seulement de l'argument DllMain pendant DLL_PROCESS_ATTACH alors vous ne devriez pas appeler FreeLibraryAndExitThread puisque le code qui a chargé le dll utilise encore et ce module gérer n'est vraiment pas à vous de gérer.

Questions connexes