Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

Проблемы с 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 вся ветка

Текущий архив: 2005.03.06;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.035 c
6-1104493151
uny
2004-12-31 14:39
2005.03.06
Закачка в несколько секций по локальной сети - как?


14-1108022908
Хинт
2005-02-10 11:08
2005.03.06
Хостинг: h15 (holm) vs fatal


14-1108452967
syte_ser78
2005-02-15 10:36
2005.03.06
заказ страниц на email


10-1085398909
Koster
2004-05-24 15:41
2005.03.06
Как использовать в Delphi тип, объявленный внутри OLE объекта?


1-1109098654
Breakmaster
2005-02-22 21:57
2005.03.06
virtual key code