Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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
14-1108149117
Nik8.
2005-02-11 22:11
2005.03.06
"Внутреннее устройство Windows 2000" Книга найдена.


3-1107862956
Mishenka
2005-02-08 14:42
2005.03.06
Как с помощью DBImage просмотреть gif ы из базы?


1-1108668519
Redhopter
2005-02-17 22:28
2005.03.06
Приведение типов


1-1108808059
Kiriill
2005-02-19 13:14
2005.03.06
EXE


1-1109150078
Object
2005-02-23 12:14
2005.03.06
Картинки в ListBox





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский