Форум: "WinAPI";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
ВнизПроблемы с CreateFileMapping и MapViewOfFile Найти похожие ветки
← →
pmm © (2005-01-24 08:34) [0]Ставлю хук в длл. Прога на всех платформах выдает ошибку типа "память не может быть рид" и проч. Сначала, правда работает 1-2 минуты. Делал по примеру из инета, пример также глючит. Почему так? А нельзя ли другой способ сделать - обратится к общей ячеи памяти разными экземплярами дллек.
И глучит на 98 на 2000 на ХП.
← →
Digitman © (2005-01-24 09:58) [1]
> Почему так?
потому что ошибки в алгоритме.
> А нельзя ли другой способ сделать - обратится к общей ячеи
> памяти разными экземплярами дллек
для этого как раз механизм MMF и предназначен
← →
pmm © (2005-01-24 10:56) [2]какие же ошибки там? брал здесь
http://www.delphirus.net.ru/printout65.html
← →
Digitman © (2005-01-24 12:06) [3]
> pmm © (24.01.05 10:56) [2]
ты СВОЙ РЕАЛЬНЫЙ код приводи ! а не тот что брал за основу ..
← →
Eraser © (2005-01-24 12:28) [4]pmm
Скорее всего или ошибка с "общей" памятью (в хуках такое у новичков часто случается), или неправильная обработка кодов хука.
Короче приводи код вместе с глобальными переменными.
← →
pmm © (2005-01-24 13:25) [5]мне нужно отследить бездействие пользователя на компе. Здесь, в длл, при каждом событии мыши пытаюсь положить в память количество "системных" тиков в милисекундах.
В основной программе таймером каждую минуту считываю эту ячею и сравниваю с текщим положением дел, ну и прочее...
DLL:
library hookdll;
uses
Windows, Messages, SysUtils, Classes;
{$R *.res}
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
Znach: DWord;
end;
const
MMFName: PChar = "KeyMMFDrozd";
var
GlobalData: PGlobalDLLData;
MMFHandle: THandle;
Hm : THandle;
function hookm(c0de, wParam, lParam : integer): Lresult; stdcall;
begin
If c0de >= 0 Then
Begin
GlobalData^.Znach := GetTickCount();
End;
result := CallNextHookEx(Hm, c0de, wParam, lParam);
end;
function ShowMeTick:DWord; export; stdcall;
begin
result := GlobalData^.Znach;
end;
procedure sethook;export; stdcall;
begin
Hm:= SetWindowsHookEx(WH_MOUSE, @hookm, hInstance, 0);
if Hm = 0 then
messagebox(0,"Ошибка","ERROR",mb_iconhand);
end;
procedure removehook;export; stdcall;
begin
UnhookWindowsHookEx(Hm);
end;
//-----------------------------------------------------------------------------
procedure OpenGlobalData();
begin
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(PGlobalDLLData), MMFName);
if MMFHandle = 0 then
begin
MessageBox(0, "Can""t create FileMapping", "from dll", 0);
Exit;
end;
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_WRITE {FILE_MAP_ALL_ACCESS}, 0, 0, SizeOf(PGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Can""t make MapViewOfFile", "from 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: CloseGlobalData;
end;
end;
//////////////////////////////////////////
exports //
sethook name "myhookset", //
removehook name "myhookrem", //
ShowMeTick name "showmetick"; //
//////////////////////////////////////////
begin
DLLProc:= @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
GlobalData^.Znach := GetTickCount();
end.
Основная программа, например, такая:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, DateUtils, ComCtrls;
procedure SetHook; External "hookdll.dll" name "myhookset";
procedure UnSetHook; External "hookdll.dll" name "myhookrem";
function ShowMeTick:DWord; External "hookdll.dll" name "showmetick";
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Timer1: TTimer;
Edit2: TEdit;
Edit3: TEdit;
Edit4: TEdit;
Edit5: TEdit;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
SetHook;
Timer1.Interval := 1000;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
UnSetHook;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
var
Per: DWord;
begin
Per := (GetTickCount() - ShowMeTick);
Edit1.Text := IntToStr(Per);
end;
end.
Как кажется, все просто до безобразия, но что-то не работает :-(
← →
Eraser © (2005-01-24 13:36) [6]Всё вроде верно, но мне кажется всё дело в передаче данных в приложение, попробуй упростить это всё и используй, например, сообщения.
И вообще бездействие пользователя ослеживается по-другому, не помню как, но недавно пример видел, там точно такого не было...
← →
pmm © (2005-01-24 13:44) [7]2Eraser
Такой же абсолютно пример я и взял из инета, только он был с сообщениями и я его "упростил под себя". Так вот он ту же ошибку выдает, хотя примерчик этот опубликован на многих сайтах и примерно один и тот же, и автор утверждает что все работает круто. Я на всех платформах проверял и на нескольких компьютерах -- выдает ошибку.
А бездействие в ХР или 2к очень просто отследить, там функция АПИшная есть, а вот в 98 нет такой функции - нужно ловушкой.
← →
Digitman © (2005-01-24 14:25) [8]
> pmm © (24.01.05 13:44) [7]
по-моему рановато тебе хуками заниматься.
ты даже о соблюдении соглашений о вызовах, видимо, понятия не имеешь ... содрал где-то stdcall, влупил его в свой код где надо и где не надо, и сидишь-ждешь, что все само-собой заработает ...
← →
Eraser © (2005-01-24 15:02) [9]Вообще stdcall должен быть только около функции обратного вызова, но по идеи что плохого, если и не только возле неё.
Я одно время ко всем экспортируемым функциям приписывал stdcall (тоже содрал где-то ;-))- работало. Правда не знаю как насчёт hookdll...
← →
BiN © (2005-01-24 15:41) [10]Вообще stdcall должен быть только около функции обратного вызова, но по идеи что плохого, если и не только возле неё.
Ты хоть сам понял, что сказал?
← →
Eraser © (2005-01-24 16:09) [11]BiN ©
Я имею ввиду, что функция обратного вызова обязана вызываться с соглашением о вызовах stdcall, а экспортируемые функции не обязаны, правда если их объявлять без stdcall их будет проблемотично использовать например из MSVC++.
← →
BiN © (2005-01-24 16:22) [12]Я имею ввиду, что функция обратного вызова обязана вызываться с соглашением о вызовах stdcall
Вероятно, имеется ввиду все-таки функция обратного вызова функции SetWindowsHookEx?
← →
Eraser © (2005-01-24 16:53) [13]BiN ©
Да.
← →
pmm © (2005-01-24 16:54) [14]Так, понятно, что ничего не понятно.
Мне то что делать? Я никогда не интересовался, что такое stdcall, но что то я сомневаюсь что дело в нем.
← →
Eraser © (2005-01-24 16:59) [15]pmm ©
я сомневаюсь что дело в нем.
Я тоже ;-))
← →
GuAV © (2005-01-24 17:23) [16]
>pmm ©
>я сомневаюсь что дело в нем.
> Я тоже ;-))
А я таки вижу проблему
> procedure DLLEntryPoint(dwReason: DWord); stdcall;
См справку по DLLProc. где там stdcall ?
Плюс есть ещё проблемы, с stdcall которые пока не сказываются на работу, но тем не менее следует разобраться и испавить.
И ещё, в 9х могут быть проблемы с CallNextHookEx, т.к. там перый параметр CallNextHookEx не игнорируется.
← →
pmm © (2005-01-24 20:42) [17]Все теперь работает [16].
Спасибо люди добрые, и злым (Digitman) тоже спасибо.
← →
GuAV © (2005-01-24 21:51) [18]Надеюсь это тоже учтено
> Плюс есть ещё проблемы, с stdcall которые пока не
> сказываются на работу, но тем не менее следует
>разобраться и испавить.
>
> И ещё, в 9х могут быть проблемы с CallNextHookEx, т.к.
> там перый параметр CallNextHookEx не игнорируется.
← →
pmm © (2005-01-25 07:35) [19]Полдня гоняю уже, все путем работает, на всех платформах. :-)
← →
GuAV © (2005-01-25 08:25) [20]pmm © (25.01.05 7:35) [19]
Это ещё не значит что ошибок нет.
хинт:
Почему приходится использовать MMF для Znach ?
Чему равен Hm для разных экземпляров библиотеки, если он не в GlobalData ?
В 9х надо передавать в CallNextHookEx именно Hm. Иначе могут быть проблемы, причём не с твоим хуком, а с другими.
И вот не-согласование:
в dll
> procedure sethook;export; stdcall;
в ехе
> procedure SetHook; External "hookdll.dll" name
> "myhookset";
работает только потому что параметров нет вообще.
← →
pmm © (2005-01-25 11:09) [21]Соглаасен, что так.
Я большой новичок в этом деле, плохо еще соображаю.
Почему приходится использовать MMF для Znach ?
А как мне сохранять Тик от разных экземляров DLL??? чтоб его потом мой ехе смог взять?
Ну вощем я тут переделал, типа думаю, что правильно исправил :-/
library hookdll;
uses
Windows, Messages, SysUtils, Classes;
{$R *.res}
type
PGlobalDLLData = ^TGlobalDLLData;
TGlobalDLLData = packed record
SysHook : HWND;
Znach : DWord;
end;
const
MMFName: PChar = "KeyMMFDrozd";
var
GlobalData : PGlobalDLLData;
MMFHandle : THandle;
//-------------------------------------------------------------------------
function hookm(c0de, wParam, lParam : integer): Lresult;
begin
If c0de >= 0 Then
Begin
GlobalData^.Znach := GetTickCount();
End;
result := CallNextHookEx(GlobalData^.SysHook, c0de, wParam, lParam);
end;
//-------------------------------------------------------------------------
function ShowMeTick:DWord; export;
begin
result := GlobalData^.Znach;
end;
//-------------------------------------------------------------------------
procedure SetHook; export;
begin
GlobalData^.SysHook := SetWindowsHookEx(WH_MOUSE, @hookm, hInstance, 0);
if GlobalData^.SysHook = 0 then
messagebox(0,"Error SetWindowsHookEx WH_MOUSE","ERROR",mb_iconhand);
end;
//-------------------------------------------------------------------------
procedure RemoveHook; export;
begin
UnhookWindowsHookEx(GlobalData^.SysHook);
end;
//--------------------------------------------------------------------------
procedure OpenGlobalData();
begin
MMFHandle:= CreateFileMapping(INVALID_HANDLE_VALUE, nil, PAGE_READWRITE, 0, SizeOf(PGlobalDLLData), MMFName);
if MMFHandle = 0 then
begin
MessageBox(0, "Can""t create FileMapping", "from dll", 0);
Exit;
end;
GlobalData:= MapViewOfFile(MMFHandle, FILE_MAP_WRITE, 0, 0, SizeOf(PGlobalDLLData));
if GlobalData = nil then
begin
CloseHandle(MMFHandle);
MessageBox(0, "Can""t make MapViewOfFile", "from dll", 0);
Exit;
end;
end;
//-----------------------------------------------------------------------------
procedure CloseGlobalData();
begin
UnmapViewOfFile(GlobalData);
CloseHandle(MMFHandle);
end;
//-----------------------------------------------------------------------------
procedure DLLEntryPoint(dwReason: DWord);
begin
case dwReason of
DLL_PROCESS_ATTACH: OpenGlobalData;
DLL_PROCESS_DETACH: CloseGlobalData;
end;
end;
//*************************************
exports
SetHook name "myhookset",
RemoveHook name "myhookrem",
ShowMeTick name "showmetick";
//*************************************
begin
DLLProc:= @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
GlobalData^.Znach := 0;
end.
EXE
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, DateUtils, ComCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Edit1: TEdit;
Timer1: TTimer;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Timer1Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
SetHook:procedure;
UnSetHook:procedure;
ShowMeTick:function:DWord;
fhand:Thandle;
implementation
{$R *.dfm}
//---------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
begin
@SetHook := nil;
@UnSetHook := nil;
@ShowMeTick := nil;
fhand := LoadLibrary("hookdll.dll");
@SetHook := GetProcAddress(fhand,"myhookset");
@UnSetHook := GetProcAddress(fhand,"myhookrem");
@ShowMeTick := GetProcAddress(fhand,"showmetick");
SetHook;
Timer1.Interval := 1000;
end;
//---------------------------------------------------
procedure TForm1.Button2Click(Sender: TObject);
begin
UnSetHook;
end;
//---------------------------------------------------
procedure TForm1.Timer1Timer(Sender: TObject);
var
Period: DWord;
begin
Period := (GetTickCount() - ShowMeTick);
Edit1.Text := IntToStr(Period);
end;
//---------------------------------------------------
end.
← →
GuAV © (2005-01-25 23:44) [22]
> Ну вощем я тут переделал, типа думаю, что правильно
> исправил :-/
Да. SysHook должен быть общим для всех экземпляров dll.
Только не везде нужно было убрать stdcall. Всё же наверное следует разобраться что есть stdcall и вообще соглашения о вызовах.
Смысла перехода от импорта к LoadLibrary/GetProcAddress не вижу, однако если уже LoadLibrary неплохо бы и проверить результат. Также следует вызывать FreeLibrary.
← →
Digitman © (2005-01-26 08:38) [23]
> pmm © (24.01.05 20:42) [17]
> злым (Digitman)
"злой Digitman" иногда справку стандартную почитывает, знаешь ли.
а "добрый ppm" не удосуживается.
а в справке той написано :
The WH_MOUSE hook enables you to monitor mouse messages about to be returned by the GetMessage or PeekMessage function
и что будет делать "добрый ppm", если фокусом в течение длит.времени обладает некое консольное приложение, не вызывающее ни GetMessage ни PeekMessage ?
← →
pmm © (2005-01-26 12:24) [24]Только не везде нужно было убрать stdcall. Всё же наверное следует разобраться что есть stdcall и вообще соглашения о вызовах.
Да, с stdcall у меня большие пробелы, что-то не могу нигде полноценную статью найти, может подкинет кто ссылку грамотную :-), как бы разобраться. А подключал через LoadLibrary/GetProcAddress так просто, а про Free.. забыл немного. (Совсем Без stdcall 98ой падает напроч.).
> и что будет делать "добрый ppm", если фокусом в течение
> длит.времени обладает некое консольное приложение, не вызывающее
> ни GetMessage ни PeekMessage ?
Гонял и с консолью, все норамльно работает.
← →
Digitman © (2005-01-26 12:33) [25]
> забыл немного
"Так не бывает - тут помню, а тут не помню" (с)
это как ? чуть-чуть беременный что ли ?)
> что-то не могу нигде полноценную статью найти
тему "calling conventions" в станд.справке изучал ?
> Гонял и с консолью, все норамльно работает
ой не верю.
а кроме консолей, заметь, есть еще и ntvdm-процессы, эмулирующие ДОС-среду для ДОС-задач.. какие нафих в ДОС GetMessage или PeekMessage ?
ты не в ту степпь подался ... если уж решать задачу с пом.хук-механизма, то ставить нужно хуки WH_LL_KEYBOARD и WH_LL_MOUSE
← →
pmm © (2005-01-26 13:31) [26]
> тему "calling conventions" в станд.справке изучал ?
почитал, написано мало, и основных принципов при работе с АПИфункцими я там так и не нашел
> ой не верю.
сам возьми, проверь. лист программы приводиться, заодно и stdcall проставь где нужно.
Такое глубокое системное программирование - не мой профиль, и в каком порядке передаются параметры в процедуру, мне честно говоря все равно; поэтому то я сюда и обратился, а нужно то было только отследить бездействие пользователя за компом. а досПриложений у нас на предприятии давно нет
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.104 c