Форум: "WinAPI";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];
ВнизОпять Hook DLL :) Найти похожие ветки
← →
Goorus © (2005-02-12 12:50) [0]Пишу компонент, для перехвата событий клавиатуры и мыши. Хотел избавиться от SendMessage при получении сообщения, но ничего не получилось :(
Если вызывать RunHook, то сообщения перехватываются до тех пор, пока приложение активно, если оно теряет фокус, то AppProcKeybrd больше не вызывается, даже если фокус вернуть.
В прнципе, выриант RunHook2 работает нормально, но просто не хотелось бы лишний раз отсылать сообщение.
Вот код библиотеки:
library HookLibrary;
uses
Windows, Messages;
const
MMFName = "g_HookMs";
type
TObjHookProc = procedure(WParam: WParam; LParam: LParam)of object;
TGlobalData = record
shKeybrd: HWnd; // дескриптор ловушки клавы
shMouse : HWnd; // ловушки мыши
shKeybrd2: HWnd;
AppWnd: HWnd;
end;
PGlobalData = ^TGlobalData;
var
AppProcKeybrd: TObjHookProc;
AppProcMouse : TObjHookProc;
InWorking: Boolean = False;
Runing: Boolean = False;
MMFHandle: THandle;
GlobalData: PGlobalData;
function SysMsgKeybrdProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
with GlobalData^ do
if (code = HC_ACTION) and (not InWorking) then
try
InWorking := True;
AppProcKeybrd(WParam, LParam);
finally
Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
InWorking := False;
end
else
Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
end;
function SysMsgKeybrdProc2(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
with GlobalData^ do
if (code = HC_ACTION) and (not InWorking) then
try
InWorking := True;
SendMessage(AppWnd, WH_KEYBOARD, wParam, LParam);
finally
Result := CallNextHookEx(shKeybrd2, Code, wParam, LParam);
InWorking := False;
end
else
Result := CallNextHookEx(shKeybrd2, Code, wParam, LParam);
end;
function SysMsgMouseProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
with GlobalData^ do
if (code = HC_ACTION) and (not InWorking) then
try
InWorking := True;
AppProcMouse(WParam, LParam);
finally
Result := CallNextHookEx(shMouse, Code, wParam, LParam);
InWorking := False;
end
else
Result := CallNextHookEx(shMouse, Code, wParam, LParam);
end;
function RunHook(OnKeybrd, OnMouse: TObjHookProc): Boolean; export; stdcall;
begin
Result := False;
with GlobalData^ do
if not Runing then
try
AppProcKeybrd := OnKeybrd;
AppProcMouse := OnMouse;
if not(Assigned(OnKeybrd) or Assigned(OnMouse)) then Exit;
if Assigned(OnKeybrd) then
shKeybrd := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc, hInstance, 0);
if Assigned(OnMouse) then
shMouse := SetWindowsHookEx(WH_MOUSE, @SysMsgMouseProc, hInstance, 0);
Result := True;
Runing := True;
except
end;
end;
function RunHook2(OnKeybrd: HWnd): Boolean; export; stdcall;
begin
Result := False;
with GlobalData^ do
if not Runing then
try
AppWnd := OnKeybrd;
shKeybrd2 := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc2, hInstance, 0);
Result := True;
Runing := True;
except
end;
end;
procedure StopHook(); export; stdcall;
begin
with GlobalData^ do
try
UnHookWindowsHookEx(shKeybrd);
UnHookWindowsHookEx(shMouse);
UnHookWindowsHookEx(shKeybrd2);
finally
shKeybrd := 0;
shMouse := 0;
shKeybrd2 := 0;
end;
Runing := False;
end;
procedure OpenGlobalData;
begin
// получаем объект файлового отображения
MMFHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
0, SizeOf(TGlobalData), MMFName
);
if MMFHandle = 0 then
begin
MessageBox(0, "Невозможно создать FileMapping", "Сообщение из HookLib.dll", 0);
Exit;
end;
// отображаем глобальные данные на АП вызывающего процесса и
// получаем указатель на начало выделенного пространства
GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0,
SizeOf(TGlobalData)
);
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Невозможно создать MapViewOfFile", "Сообщение из HookLib.dll", 0);
Exit;
end;
end;
procedure CloseGlobalData;
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_PROCESS_ATTACH: OpenGlobalData;
DLL_PROCESS_DETACH: begin
if Runing then StopHook;
CloseGlobalData;
end;
end;
end;
exports RunHook;
exports RunHook2;
exports StopHook;
begin
DLLProc := @DLLEntryPoint;
// вызываем назначенную процедуру для отражения
// факта присоединения данной библиотеки к процессу
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
← →
GuAV © (2005-02-12 15:38) [1]
> SendMessage(AppWnd, WH_KEYBOARD, wParam, LParam);
WH_KEYBOARD = WM_DESTROY. очень интересное совпадение.
см. справку по WM_USER
> procedure DLLEntryPoint(dwReason: DWord); stdcall;
А почему не safecall ?
> AppProcKeybrd := OnKeybrd;
> AppProcMouse := OnMouse;
Ну во первых метод по сути пара указателей - на код и на экземпляр объекта. Угадай, какой из них будет валидным в чужом АП.
И кстати зачем этот трюк с GlobalData ?
Следует не тупо коприрвать пример а разобраться в этом прежде чем применят хуки.
← →
Goorus © (2005-02-12 18:00) [2]> А почему не safecall ?
Работает - не трогай! Золотое правило :)
На счёт трюка с GlobalData, опыты показали, что shKeybrd
(shMouse, shKeybrd2) должны находиться именно там, иначе не работает.
> WH_KEYBOARD = WM_DESTROY
Это не имеет значения, у меня свой обработчик.
Про метод я понимаю, только не понимаю, почему он перестаёт быть валидным когда приложение перестаёт быть активным. Ведь DLL подключена к моему приложению.
Или, когда фокус получает другое приложения, DLL начинает пытаться вызвать эти методы у него? Сам не верю в то, что сказал :)
← →
Piter © (2005-02-12 18:03) [3]Goorus © (12.02.05 18:00) [2]
> А почему не safecall ?
Работает - не трогай!
а-а-а-а... я сейчас сползу со стула...
← →
GuAV © (2005-02-12 20:15) [4]
> На счёт трюка с GlobalData, опыты показали, что
>shKeybrd
> (shMouse, shKeybrd2) должны находиться именно там,
> иначе не работает.
Жаль. Следует всё же понять почему shKeybrd, shMouse, shKeybrd2 должны быть именно там. Здесь лежит одна из причин
> почему он перестаёт быть валидным когда приложение
> перестаёт быть активным
Другая причина - здесь.
> DLL начинает пытаться вызвать эти методы у него?
> Ведь DLL подключена к моему приложению.
Нет. Точнее не только.
> Работает - не трогай! Золотое правило :)
Жаль. А я хотел помочь...
> Это не имеет значения, у меня свой обработчик.
Ну и что. Выпенреж может стоить геморроя.
Читай
http://www.delphimaster.ru/articles/hooks/index.html
← →
Grief © (2005-02-12 23:14) [5]скопируй другой пример :)
например, мой - посылает мессаи события мыши и клавы сразу:library Catcher;
uses Messages, Windows;
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = record
KeyBoardHook: HWND;
MouseHook: HWND;
end;
var
GlobalData: PGlobalDLLData;
MMFHandle: THandle;
WM_MouseHook, WM_KeyboardHook: Cardinal;
function MouseProc(Code: Integer; WParam: Word; LParam: Longint): Longint; stdcall;
begin
if Code = HC_Action then PostMessage(HWND_Broadcast, WM_MouseHook, WParam, LParam);
MouseProc := CallNextHookEx(GlobalData^.MouseHook, Code, WParam, LParam);
end;
function KeyboardProc(Code: Integer; WParam: Word; LParam: Longint): Longint; stdcall;
begin
if Code = HC_Action then PostMessage(HWND_Broadcast, WM_KeyboardHook, WParam, LParam);
KeyboardProc := CallNextHookEx(GlobalData^.KeyBoardHook, Code, WParam, LParam);
end;
procedure Hook(Switch: Boolean); export; stdcall;
begin
if Switch = True then begin
GlobalData^.MouseHook := SetWindowsHookEx(WH_Mouse, @MouseProc, HInstance, 0);
if GlobalData^.MouseHook = 0 then
MessageBox(0, "Не удается установить ловушку для мыши!", "Критическая ошибка", MB_IconError);
GlobalData^.KeyboardHook := SetWindowsHookEx(WH_Keyboard, @KeyboardProc, HInstance, 0);
if GlobalData^.KeyBoardHook = 0 then
MessageBox(0, "Не удается установить ловушку для клавиатуры!", "Критическая ошибка", MB_IconError);
end
else begin
if UnhookWindowsHookEx(GlobalData^.KeyBoardHook) = False then
MessageBox(0, "Не удается снять ловушку для клавиатуры!", "Критическая ошибка", MB_IconError);
if UnhookWindowsHookEx(GlobalData^.MouseHook) = False then
MessageBox(0, "Не удается снять ловушку для мыши!", "Критическая ошибка", MB_IconError);
end;
end;
procedure OpenGlobalData;
begin
WM_KeyboardHook := RegisterWindowMessage("WM_KeyboardHook");
WM_MouseHook := RegisterWindowMessage("WM_MouseHook");
MMFHandle := CreateFileMapping(Invalid_Handle_Value, nil, PAGE_ReadWrite, 0, SizeOf(TGlobalDLLData), "MyMMF");
if MMFHandle = 0 then
MessageBox(0, "Can""t create FileMapping", "Message from Exampel2/Process2", 0);
GlobalData := MapViewOfFile(MMFHandle, File_Map_All_Access, 0, 0, SizeOf(TGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Can""t make MapViewOfFile", "Кртитическая ошибка", 0);
end;
end;
procedure CloseGlobalData;
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
procedure DLLEntryPoint(dwReason: DWord); stdcall;
begin
case dwReason of
DLL_Process_Attach: OpenGlobalData;
DLL_Process_Detach: CloseGlobalData;
end;
end;
exports Hook;
begin
DLLProc:= @DLLEntryPoint;
DLLEntryPoint(DLL_Process_Attach);
end.
← →
GuAV © (2005-02-13 00:04) [6]
>скопируй другой пример :)
> например, мой
LOL
← →
Goorus © (2005-02-13 04:48) [7]>> Grief
Видишь ли, PostMessage я бы тоже не хотел использовать :)
>> GuAV
Помогите, очень прошу. Вы указываете на причины ошибки, а я не понимаю её сути.
> А почему не safecall ?
Зачем? Насколько я понимаю, safecall отличается от stdcall только тем, что берёт весь код в структуру try..except end, и в случае ошибки результатом выполнения функции будет S_EXCEPT. Разве нет?
← →
GuAV © (2005-02-13 13:13) [8]Не нужно ни safecall ни stdcall. В справке (DllProc + F1) дано объявление без указания модели. Т.е. использована register. Почему оно работает, вопрос конечно интересный. С вызовом DLL_PROCESS_ATTACH вопросов нет - как описали так и вызвали из begin..end. Что касается DLL_PROCESS_DETACH = 0, то этот параметр читается из стека, где он тоже оказывается равным 0 и "деформация" стека похоже не сказывается на выгрузке (по крайней мере сообщений об ошибках нет). Однако не факт что с выгрузкой никогда не будет проблем, а кроме того есть ещё и DLL_THREAD_ATTACH/DETACH.
Суть такова. SetWindowsHookEx(... , 0); устанавливает глобальный хук, который работает во всех потоках текущего десктопа. Следовательно эта dll загружается многими процессами. Если dll загруженна разными процессами, у каждой из них свои данные (и, возможно, код, если он будет отличатся). Инициализация происходит при загрузке каждым из процессов, соотв финализация при выгрузке каждым из процессов.
Т.е. для того чтобы какие либо переменные имели одинаковые значения во всех экземплярах dll и изменяли их при изменении в одном из экземпляров, следует возпользоваться каким либо механизмом обмеа данных между процессами, в данном случае MMF. Так, при назначении AppWnd из RunHook2, экземпляры dll загруженные позже уже получат это значение (если бы были уже загруженные в них бы тоже поменялось), что касается AppProcKeybrd, то изменение значения в экзепляре, загруженном для выполнения RunHook никак не отразится на других - в них останется неназначенный метод (глоб. переменные инициализируются нулями).
Помещение AppProcKeybrd в TGlobalData, однако, не решит проблемы. Дело в том что поскольку dll загруженна другим процессом, эти самые указатели на код и на даные будут разрешены в контексте того процесса. Что при этом поучится - неизвестно, хотя вероятно AV в большинстве случаев.
Почему методы всё же работают в своём процессе - для него используется копия загруженная для выполнения RunHook2. Почему перестают работать - там видимо библиотека подключается динамически (через вызовы loadlibrary(ex)/freelibarary), и она выгружается и вновь загружается.
Способ решения - передавать сообщения, а методы запускать только в своём компоненте. Я подозреваю что он наследник TComponent поэтому в нём следует самому создать окно для приёма сообщений. (Рекомендую воспользовать AllocateHWND, в оконном методе можно делать Dispatch, а можно просто case). Или, создать поток для приёма сообщений.
← →
GuAV © (2005-02-13 13:20) [9]GuAV © (13.02.05 13:13) [8]
Или, создать поток для приёма сообщений.
С потоком я конечно погорячился. Не следует создавать поток, который будет только спать и синхронизироваться.
← →
GuAV © (2005-02-13 14:33) [10]Да, ещё, про
> function RunHook2(OnKeybrd: HWnd): Boolean; export;
>stdcall;
>begin
> Result := False;
> with GlobalData^ do
> if not Runing then
> try
> AppWnd := OnKeybrd;
>
> shKeybrd2 := SetWindowsHookEx(WH_KEYBOARD,
>@SysMsgKeybrdProc2, hInstance, 0);
>
> Result := True;
> Runing := True;
> except
>
> end;
> end;
Такая конструкция не потокобезопасна. Т.е. если из двух приложений будут почти одновременно вызваны RunHook, то оба вызова состоятся, причём возможно shKeybrd будет соответствовать хуку одного, а shMouse - другого, а установленны быть все четыре. Поэтому лучше использовать такую конструкциюif InterlockedCompareExchange(Pointer(Running),
Pointer(True), Pointer(False)) <> Pointer(False) then
try
...
except
Runing := Fasle;
end;
Кстати except здесь IMHO не нужен. Если SetWindowsHookEx не удасться, то исключения не будет, просто он вернёт 0 (кроме случаев типа AV, stack overflow). Достаточно проверять shKeybrd <> 0.
← →
Goorus © (2005-02-13 16:02) [11]Большое спасибо :) Буду использовать SendMessage.
Ещё вопрос: тогда получается, что несколько приложений одноверменно не смогут пользоваться этой библиотекой? Ведь все они будут использовать один временный файл, в котором будут записаны данные последней запущенной библиотеки. Прийдётся имя файла брать что-то вида
MMFName + IntToStr(hInstance)
← →
GuAV © (2005-02-13 16:47) [12]Goorus © (13.02.05 16:02) [11]
Ещё вопрос: тогда получается, что несколько приложений одноверменно не смогут пользоваться этой библиотекой?
Верно.
Goorus © (13.02.05 16:02) [11]
временный файл
Это не файл, а проекция файла. В данном случае проекция page file, т.е. просто область памяти, "поддерживаемая" page file.
Goorus © (13.02.05 16:02) [11]
MMFName + IntToStr(hInstance)
Нет. Нужно брать что-то действительно уникальное. ProcessId или ThreadId подойдут.
hInstance для ехе практически всегда = ImageBase = $00400000, для Dll в лучшем случае равно ImageBase, в общем - что угодно.
Причём помимо разделения по приложениям ещё следует учесть возможность двух и более копий компонента в одном приложении. Если такую возможность нужно предусмотреть, то следует создать только одно окно на всю библиотеку, из которого вызывать обработчики, назначенные в каждом из экземпляров компонента (придётся обеспечить учёт экземпляров компонента во внутреннем списке TComponentList).
← →
GuAV © (2005-02-13 16:57) [13]GuAV © (13.02.05 16:47) [12]
ProcessId или ThreadId подойдут.
Хотя и это не совсем верно. Исключается возможность использовать библиотеку в ехе и dll независимо. Наиболее правильным думаю будет
GetModuleFileName с параметром hInstance (не 0, а именно SysInit.HInstance)
← →
GuAV © (2005-02-13 17:08) [14]GuAV © (13.02.05 16:57) [13]
GetModuleFileName с параметром hInstance (не 0, а именно SysInit.HInstance)
Причём SysInit.HInstance должнен быть взят из кода модуля компонента, а не dll. Т.е. выходит что его нужно передать как параметр RunHook.
← →
Goorus © (2005-02-13 17:21) [15]Спасибо ещё раз.
← →
GuAV © (2005-02-13 22:35) [16]Блин, я туплю..
Самый уникальный идентификатор, чтобы прибавить к MMFName - это AppWnd !
← →
Piter © (2005-02-14 01:03) [17]GuAV © (13.02.05 22:35) [16]
Самый уникальный идентификатор, чтобы прибавить к MMFName - это AppWnd !
а чем он уникальнее, например, ID процесса или потока?
И нет никакой гарантии, что кто-то не прибавит AppWnd твоего процесса.
Так что 100% уникальность гарантировать нельзя, ясное дело.
← →
Goorus © (2005-02-14 03:11) [18]Это мелкий вопрос, в принципе, имя файла никого не волнует, так что можно брать AppWnd + Random + GetTickCount, придумаю что-нибудь.
← →
GuAV © (2005-02-14 08:34) [19]Piter © (14.02.05 1:03) [17]
а чем он уникальнее, например, ID процесса или потока?
Тем что в случае использования компонента в нескольких dll без BwRTP он будет один и тот же.
Piter © (14.02.05 1:03) [17]
И нет никакой гарантии, что кто-то не прибавит AppWnd твоего процесса.
???
← →
GuAV © (2005-02-14 08:47) [20]Хотя... отставить. Ничего со случайным идентификатором не выйдет, тк. он должен совпасть для dll загруженных данным процессам во все процессы. Придётся наверное в GlobalData массив создавать.
← →
Goorus © (2005-02-14 17:54) [21]Я опять чего-то не понял. Разве GlobalData в различных приложения будет различна? Сейчас сделал так:
library HookLibrary;
uses
Windows, Dialogs,
Messages,
ghlbTypes in "..\ghlbTypes.pas";
const
MMFName_ = "HookMsg";
var
InWorking: Boolean = False;
Runing: Boolean = False;
MMFName: String;
MMFHandle: THandle;
GlobalData: PGlobalData;
function IntToStr(const X: Int64): String;
begin
Str(X, Result);
end;
function SysMsgKeybrdProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
if not Assigned(GlobalData) then
ShowMessage("not Assigned")
else
with GlobalData^ do
if (code = HC_ACTION) and (not InWorking) then
try
InWorking := True;
SendMessage(AppWnd, GMH_KEYBOARD, wParam, LParam);
finally
Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
InWorking := False;
end
else
Result := CallNextHookEx(shKeybrd, Code, wParam, LParam);
end;
function SysMsgMouseProc(code: Integer; WParam: WParam; LParam: LParam): LResult; stdcall;
begin
with GlobalData^ do
if (code = HC_ACTION) and (not InWorking) then
try
InWorking := True;
msgMouse := TMouseHookStruct( Pointer(LParam)^ );
SendMessage(AppWnd, GMH_MOUSE, wParam, LParam);
finally
Result := CallNextHookEx(shMouse, Code, wParam, LParam);
InWorking := False;
end
else
Result := CallNextHookEx(shMouse, Code, wParam, LParam);
end;
procedure OpenGlobalData;
begin
if MMFName = "" then Exit;
if Assigned(GlobalData) then Exit;
// получаем объект файлового отображения
MMFHandle := CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE,
0, SizeOf(TGlobalData), PChar(MMFName)
);
if MMFHandle = 0 then
begin
MessageBox(0, "Невозможно создать FileMapping", "Сообщение из HookLib.dll", 0);
Exit;
end;
// отображаем глобальные данные на АП вызывающего процесса и
// получаем указатель на начало выделенного пространства
GlobalData := MapViewOfFile(MMFHandle, FILE_MAP_ALL_ACCESS, 0, 0,
SizeOf(TGlobalData)
);
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Невозможно создать MapViewOfFile", "Сообщение из HookLib.dll", 0);
Exit;
end;
end;
function RunHook(AAppWnd: HWnd): PGlobalData; export; stdcall;
begin
Result := nil;
if not Runing then
begin
// создаём уникальное имя
MMFName :=
MMFName_ + "-" + IntToStr(GetCurrentProcessId) +
"-" + IntToStr(GetCurrentThreadId) + "-" + IntToStr(AAppWnd) +
"-" + IntToStr(GetTickCount) + "-" + IntToStr( Random(MaxInt) )
;
OpenGlobalData;
with GlobalData^ do
begin
AppWnd := AAppWnd;
shKeybrd := SetWindowsHookEx(WH_KEYBOARD, @SysMsgKeybrdProc, hInstance, 0);
shMouse := SetWindowsHookEx(WH_MOUSE, @SysMsgMouseProc, hInstance, 0);
end;
Result := GlobalData;
Runing := True;
end;
end;
procedure StopHook(); export; stdcall;
begin
with GlobalData^ do
try
UnHookWindowsHookEx(shKeybrd);
UnHookWindowsHookEx(shMouse);
finally
shKeybrd := 0;
shMouse := 0;
end;
Runing := False;
end;
procedure CloseGlobalData;
begin
if Assigned(GlobalData) then
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
end;
procedure DLLEntryPoint(dwReason: DWord); register;
begin
case dwReason of
// DLL_PROCESS_ATTACH, DLL_THREAD_ATTACH: OpenGlobalData;
DLL_PROCESS_DETACH: begin
if Runing then StopHook;
CloseGlobalData;
end;
end;
end;
exports RunHook;
exports StopHook;
begin
Randomize;
DLLProc := @DLLEntryPoint;
end.
Если я нажимаю клавишу на клавиатуре в другом приложении, сообщение "not Assigned" появляется.. Но почему? Ведь GlobalData ссылается на MapViewOfFile, а оно ведь не привязано к приложению?
В ghlbTypes:
type
TGlobalData = record
shKeybrd: HWnd; // дескриптор ловушки клавы
shMouse : HWnd; // ловушки мыши
AppWnd: HWnd;
// данные хука
msgMouse: TMouseHookStruct;
end;
PGlobalData = ^TGlobalData;
var
GMH_KEYBOARD: Cardinal;
GMH_MOUSE: Cardinal;
...
← →
GuAV © (2005-02-14 19:12) [22]Goorus © (14.02.05 17:54) [21]
// создаём уникальное имя
MMFName :=
MMFName_ + "-" + IntToStr(GetCurrentProcessId) +
"-" + IntToStr(GetCurrentThreadId) + "-" + IntToStr(AAppWnd) +
"-" + IntToStr(GetTickCount) + "-" + IntToStr( Random(MaxInt) )
;
Так не получится.... немного раньше в [20] об этом написал. Если нужно несколько копий, придётся массив внутри globaldata делать...
← →
Goorus © (2005-02-15 03:53) [23]Тесты показали.. :)
DLL подключается к другому приложению, когда в нём происходит отлавливаемое событие, при этом MMFName = "", а GlobalData = nil.
То есть все переменные сбрасываются.. Точнее библиотека заново загружается и подключается к этому рпиложению. Но тогда получается, что библиотека никак не сможет узнать к какому же приложению она на самом деле подключена, т.е. создать библиотеку, которую можно использовать сразу в нескольких приложениях невозможно?!
Даже если создать в GlobalData массив, DLL не будет знать, к какому элементу обращаться... индекс ведь опять нужно хранить вне библиотеки, где он опять же будет переписан другой ДЛЛ...
← →
Digitman © (2005-02-15 08:40) [24]
> DLL подключается к другому приложению, когда в нём происходит
> отлавливаемое событие
точнее сказать, DLL загружается в АП целевого процесса
> при этом MMFName = "", а GlobalData = nil
> То есть все переменные сбрасываются
сколько будет этих целевых процессов, столько будет и экземпляров данных DLL
> библиотека никак не сможет узнать к какому же приложению
> она на самом деле подключена
почему не может ? может !
см. GetModuleHandle + GetModuleFileName
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];
Память: 0.56 MB
Время: 0.05 c