KDM
asked on
SetWindowsHookEx()
I am developing a program that monitors keyboard and mouse activity independently of screen saver routines. I am trying to do this via the journal record hook. My program compiles okay, but I get a "this program has performed an illegal operation" whenever I try to run it (in or out of MFC Development Studio). According to the MFC documentation, a Win32 journal record hook does not need to have a separate DLL for its hook procedure. My code is structured as follows in the MyApp.cpp file:
BOOL CMyApp::InitInstance()
{
// MFC's generated stuff
....
....
// Initialize my variables to be used
// in the journal proc, OnIdle()
m_IdleFileName = "c:\mydir\Myfile.dat";
m_InIdle = FALSE;
m_IdleCount = 0;
m_IdleOffset = 15;
// Set the journal record hook
m_Hook = SetWindowsHookEx(WH_JOURNA LRECORD,
JnlRecProc, NULL, 0);
if(m_Hook == NULL)
{
AfxMessageBox("Initializat ion error");
return FALSE;
}
return TRUE;
}
/* Idle Time Procedure (Assumption: This is called whenever the program has an empty queue -- When there is no journal recording. */
BOOL CMyApp::OnIdle(long lcount)
{
// Get the current time
m_Now = CTime::GetCurrentTime();
// On the first call, set the idle flag
// and get ready to count
if(lcount == 1)
{
m_InIdle = TRUE;
m_IdleCount = 0;
}
else
{
m_MinutesElapsed = m_Now - m_LastActivity;
m_IdleCount =
m_MinutesElapsed.GetTotalM inutes();
}
return CWinApp::OnIdle(lcount);
}
// Journal Record Procedure
LRESULT CALLBACK CMyApp::JnlRecProc(int ncode,
WPARAM wparam, LPARAM lparam)
{
switch(ncode) {
case HC_ACTION:
m_LastActivity = CTime::GetCurrentTime();
// if idle time processing has taken place,
// save the idle count
if(m_InIdle)
{
if(m_IdleCount > m_IdleOffset)
m_IdleCount -= m_IdleOffset;
else
m_IdleCount = 0;
// Read accumulated idle time from file
if((fp = fopen(m_IdleFileName, "r")) != NULL)
{
if(fread(&m_IdleTime, sizeof m_IdleTime,
1, fp) != 1)
m_IdleTime = m_IdleCount;
else
m_IdleTime += m_IdleCount;
fclose(fp);
}
else
m_IdleTime = m_IdleCount;
// Write new value to file
if((fp = fopen(m_IdleFileName, "w")) != NULL)
{
m_Result = fwrite(&m_IdleTime,
sizeof m_IdleTime, 1, fp);
fclose(fp);
}
// Reset flag m_InIdle
m_InIdle = FALSE;
}
break;
case HC_SYSMODALON:
case HC_SYSMODALOFF:
break;
default:
break;
}
return(CallNextHookEx(m_Ho ok, ncode, wparam, lparam);
}
When I try to debug this, my computer locks up. It appears that the breakdown is occurring within the journal record procedure (and not when the hook is being set).
Can anyone give me a clue as to what is happening here?
Thanks!
BOOL CMyApp::InitInstance()
{
// MFC's generated stuff
....
....
// Initialize my variables to be used
// in the journal proc, OnIdle()
m_IdleFileName = "c:\mydir\Myfile.dat";
m_InIdle = FALSE;
m_IdleCount = 0;
m_IdleOffset = 15;
// Set the journal record hook
m_Hook = SetWindowsHookEx(WH_JOURNA
JnlRecProc, NULL, 0);
if(m_Hook == NULL)
{
AfxMessageBox("Initializat
return FALSE;
}
return TRUE;
}
/* Idle Time Procedure (Assumption: This is called whenever the program has an empty queue -- When there is no journal recording. */
BOOL CMyApp::OnIdle(long lcount)
{
// Get the current time
m_Now = CTime::GetCurrentTime();
// On the first call, set the idle flag
// and get ready to count
if(lcount == 1)
{
m_InIdle = TRUE;
m_IdleCount = 0;
}
else
{
m_MinutesElapsed = m_Now - m_LastActivity;
m_IdleCount =
m_MinutesElapsed.GetTotalM
}
return CWinApp::OnIdle(lcount);
}
// Journal Record Procedure
LRESULT CALLBACK CMyApp::JnlRecProc(int ncode,
WPARAM wparam, LPARAM lparam)
{
switch(ncode) {
case HC_ACTION:
m_LastActivity = CTime::GetCurrentTime();
// if idle time processing has taken place,
// save the idle count
if(m_InIdle)
{
if(m_IdleCount > m_IdleOffset)
m_IdleCount -= m_IdleOffset;
else
m_IdleCount = 0;
// Read accumulated idle time from file
if((fp = fopen(m_IdleFileName, "r")) != NULL)
{
if(fread(&m_IdleTime, sizeof m_IdleTime,
1, fp) != 1)
m_IdleTime = m_IdleCount;
else
m_IdleTime += m_IdleCount;
fclose(fp);
}
else
m_IdleTime = m_IdleCount;
// Write new value to file
if((fp = fopen(m_IdleFileName, "w")) != NULL)
{
m_Result = fwrite(&m_IdleTime,
sizeof m_IdleTime, 1, fp);
fclose(fp);
}
// Reset flag m_InIdle
m_InIdle = FALSE;
}
break;
case HC_SYSMODALON:
case HC_SYSMODALOFF:
break;
default:
break;
}
return(CallNextHookEx(m_Ho
}
When I try to debug this, my computer locks up. It appears that the breakdown is occurring within the journal record procedure (and not when the hook is being set).
Can anyone give me a clue as to what is happening here?
Thanks!
Does this happen error come up whenever you run your application from command line or explorer. If it doesnot, maybe some of MSVC's hooks are interferring with your application.
does it die if you do nothing in your journal callback (comment out all code)?
ASKER
The program dies no matter what I do: Build a debug or release version, run it in MFC Dev Studio or out. The program also dies if I remark out all but the CallNextHookEx() function. (The procedure must return a value.)
have you tried commenting out the sethook to make sure it sin't the onIdle handler ... also do you have a crash address for your program? if you have you tried using the map file to look up the spot it is dying at?
ASKER
I have tried commenting out the SetWindowsHookEx() and the journal record procedures. The program compiles and runs without a problem. (Of course, it doesn't really DO anything without the hook!)
I do get a crash address, but unfortunately, I don't know what to do with it. What is a map file? (More importantly, how can I take a look at it?)
I do get a crash address, but unfortunately, I don't know what to do with it. What is a map file? (More importantly, how can I take a look at it?)
I have developed hooks under NT and 95 without any trouble. Instead of using Journal playback try using Mouse and Keyboard hooks directly. You can also use the WindowProc hook.
If you still have problems and want a source code well , hype your points to about 200 and make sure you give a A grade if satisfied. If this is ok with you send me your e-mail address.
If you still have problems and want a source code well , hype your points to about 200 and make sure you give a A grade if satisfied. If this is ok with you send me your e-mail address.
Also another thing. Why are you using MFC to do system critical tasks like hooks ? MFC will only slow down the process. This can be achieved using simple C. MFC is good only for UI based apps. System critical tasks like hooks, thunks , SSO's should avoid MFC or any other class libs as much as possible.
ASKER
I hate to reject you like this, but you have given me an almost non-answer. (I don't have 200 points right now anyway.)
I investigated using keyboard and mouse hooks before trying the journal hook. With keyboard/mouse hooks, I would have to develop a separate DLL to hold their procedures. For a lot of reasons I won't go into here, I don't want to do that. (If I were developing this project for myself, I'd take the time to do it. But this is for work, and they want something NOW.)
Now, as to your other question: I am using MFC because it's all I have. If I were to use simple C (as you suggest), I would be forced to write all the Windows overhead code myself. This is my first attempt at writing Windows applications, so I'd have no idea how to begin. This program is just one of several, most of which are using an SDI to one or more FoxPro databases. I'm just using the same tools I used to do the other programs.
I investigated using keyboard and mouse hooks before trying the journal hook. With keyboard/mouse hooks, I would have to develop a separate DLL to hold their procedures. For a lot of reasons I won't go into here, I don't want to do that. (If I were developing this project for myself, I'd take the time to do it. But this is for work, and they want something NOW.)
Now, as to your other question: I am using MFC because it's all I have. If I were to use simple C (as you suggest), I would be forced to write all the Windows overhead code myself. This is my first attempt at writing Windows applications, so I'd have no idea how to begin. This program is just one of several, most of which are using an SDI to one or more FoxPro databases. I'm just using the same tools I used to do the other programs.
ASKER
To strobert: I figured out how to get a map file for my application. As soon as I can translate it, I might be able to figure it out. Thanks for the tip.
Does it die with just the onidle in (no set hook?)
I am more familiar with BC4.52 map files, but am starting to get used to VC ones (at a previous job I used borland, at my new one I am using VC)... have you figured out how to use it yet?
(the crash address, map thing is more usefull if you can get something akin to borland winspector stack dumps -- it will give you the each of the addresses in the call stack so if the crash is in a general routine, you can see who called it)
I am more familiar with BC4.52 map files, but am starting to get used to VC ones (at a previous job I used borland, at my new one I am using VC)... have you figured out how to use it yet?
(the crash address, map thing is more usefull if you can get something akin to borland winspector stack dumps -- it will give you the each of the addresses in the call stack so if the crash is in a general routine, you can see who called it)
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I am accepting your answer this time because I think you have mad an honest answer to help me. I have acquired the hooks example, and going through it will be my next task.
Also, I'd like to thank you for your compliment (that you didn't know I was a beginner). I certainly strive hard not to sound like one by going through every resource I have before asking others stupid questions.
Also, I'd like to thank you for your compliment (that you didn't know I was a beginner). I certainly strive hard not to sound like one by going through every resource I have before asking others stupid questions.
ASKER