2011-01-11 2 views
5

Przenoszę niektóre funkcje do współużytkowanej biblioteki DLL (chcę, aby niektóre z nich nazywały się hakiem Windows).Kod zakończenia delphi w bibliotece DLL

Rzeczywiste funkcje są obecnie w postaci unit, a zdarza się, że mają one kod initialization i niektóre finalization.

Początkowo myślałem o zrobieniu bezpośredniej transformacji z unit do library. Więc przeniosłem kod initialization pomiędzy główne begin i end.. Ale wtedy zdałem sobie sprawę, że nie mam gdzie przenieść kodu finalization. Zamiast tego powinienem utworzyć i zarejestrować specjalny punkt wejścia DLL.

Moje pytanie jest. Mogę zostawić unit ze wszystkimi funkcjami i initialization i finalization kody i po prostu stworzyć library niedopałek że uses jednostkę? czy będzie on wywoływany jako finalization?

Odpowiedz

8

kod w sekcjach inicjalizacji jednostek w DLL będzie uruchamiany, gdy DLL jest najpierw załadowane do procesu. Sekcje finalizacji są uruchamiane, gdy biblioteka DLL jest usuwana z procesu.

Eugene ma rację, że można mieć kontrolę nad bardziej precyzyjną użyciu DLLProc ale zazwyczaj jest to potrzebne tylko dla zasobów per-wątku, na przykład wątku lokalnego magazynu.

Chciałbym zauważyć, że istnieją poważne ograniczenia co do tego, co można zrobić podczas DLLMain, gdzie ostatecznie sekcje inicjalizacyjne/końcowe powstają w bibliotece. Dokumentacja MSDN w zasadzie mówi, że możesz zrobić kilka rzeczy, ale nie ma listy akceptowalnych zachowań. Najbliższe jest powiedzenie, że możesz wywoływać funkcje w kernel32. W przeciwnym razie wszystkie zakłady są wyłączone!

Istnieje wiele artykułów w Internecie, które opisują problem, ale poza tematem MSDN dla DLLMain, który mam powyżej, polecam czytanie Microsoft's Best Practices for Creating DLLs.

Pomocny rada że MSDN oferuje to, że biblioteka może upoważnić, że jego użytkownicy wywołania funkcji inicjalizacji przed użyciem DLL. Odpowiednia funkcja finalizacji zostanie wywołana, gdy skończysz z DLL. Korzystanie z comctl32.dll przyjmuje ten idiom, patrz InitCommonControlsEx.

W moim własnym kodzie preferuję alternatywne podejście. Sekcje inicjalizacji wszystkich moich jednostek rejestrują metody inicjalizacji i finalizacji. Następnie przy pierwszym wywołaniu dowolnej wyeksportowanej funkcji z mojej biblioteki uruchamiane są metody inicjowania w kolejności, w jakiej zostały zarejestrowane.Nie jest to dla mnie problemem wdrożenie, ponieważ kontroluję już wszystkie punkty wejścia/wyjścia do mojej biblioteki.

Zdaję sobie sprawę, że jest to coś więcej, niż chciałeś, ale może ci się przydać, aby uniknąć problemów, które trudno rozwiązać.

+2

+1. W skrócie, kod w sekcji finalizacji * zostanie * wywołany, ale z powodu blokady programu ładującego OS, możesz tego nie chcieć. Unikaj możliwego zakleszczenia: Eksportuj jawne funkcje inicjalizacji i finalizacji, aby proces hosta mógł wywołać. –

+0

The Old New Thing wyjaśnia, dlaczego: http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx –

+2

@Jeroen Miałem zamiar link do tego artykułu, ale to trochę jajko curate i artykuły, które Raymond łączy, wydają się być zjedzone przez zgniliznę MS link. Najlepszym odnośnikiem, jaki znalazłem, jest http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx –

4

Inicjalizacja urządzenia zostanie wywołana, jeśli jest to program i jeśli jest to biblioteka.

To samo dotyczy finalizacji.

Więc tak, można pozostawiać urządzenia jak to jest i eksportować wymaganą funkcjonalność.

0

sugeruję, że wdrożenie DllMain i obsługiwać różne sytuacje (proces załączyć, gwint dołączyć etc) przez wywołanie procedury/funkcje dedykowane dla każdej sytuacji. Następnie możesz wywołać potrzebne procedury/funkcje od inicjalizacji i finalizacji, jeśli musisz przełączyć się z DLL na jednostkę. Powodem jest to, że możesz potrzebować kontroli drobnego ziarna, gdy biblioteka DLL jest podłączona/odłączona do/z wątku (co stanie się, gdy ustawisz systemowy hak).

+0

Nie powinieneś, a The Old New Thing wyjaśnia, dlaczego: http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx –

+0

@Jeroen to są wszystkie słowa. W rzeczywistości, podczas implementowania hooków w całym systemie (i napisałem ich kilka) w wielu przypadkach trzeba użyć DLLMain i śledzić załączanie wątku. Wynika to z natury haczyków o zasięgu systemowym. –

0

To również mnie spotkało. Dowiedziałem się, że mam jednostkę, tę sekcję inicjalizacji, która tworzy wątek lub robi coś, kiedy biblioteka DLL jest zarejestrowana.

Usunąłem tę sekcję inicjalizacji i działało dobrze.

Ponieważ inicjalizacja jest wymagana dla .exe aplikacji, ale nie dla dll aplikacji jest zmienna flagi w narzędziu systemowym, zwany ModuleIsLib prostu zrobić:

initialization 

if not ModuleIsLib then 
begin 
// initialization stuff for .exe file 
end; 

Można to zrobić także za sekcja finalizacji.

mam nadzieję, że pomógł ..!