[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1537
  • Last Modified:

KillTimer doesn't work.

Hi, I am working with SetTimer and KillTimer a lot, and this is the first time that I encunter this problem.

I have a code inside Hook (SetWindowsHook) DLL.
I am doing
g_timer1=::SetTimer(NULL,1,200,gTimer1);
and the first command in in the timer I do:
void CALLBACK gTimer1(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime)
{
      ::KillTimer(0,g_timer1);
}
But the timer continue to work (is not killed).
0
VapiSoft
Asked:
VapiSoft
  • 5
  • 3
  • 3
  • +2
5 Solutions
 
ZoppoCommented:
Hi VapiSoft,

you should check the return value - if it's FALSE use GetLastError to retrieve a windows error code which might help to find the problem.

ZOPPO
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
From help files -
The KillTimer function does not remove WM_TIMER messages  already posted to the message queue.
0
 
jkrCommented:
If that is a global hook - are you sure you are doing that in the right process' context?
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
VapiSoftAuthor Commented:
To ikr = I don't understand. If do: SetTimer, than the timer proc will be called in the same process context.
How can it be another process??
To Zoppo: It is running in a client's computer so I will check it tomorrow and let you know if and what is the error that it returns.
To AndyAinscow: The problem is not the last WM_TIME but that it continues forever.
0
 
jkrCommented:
Well, if it is a global hook, it will be executed in a lot of processes, so you need to make sure that set and remove your timer in the same process.
0
 
itsmeandnobodyelseCommented:
>>>> ::KillTimer(0,g_timer1);


That is a wrong call. The first argument is the hwnd of the window that runs the message queue. It actually shouldn't be NULL but the window handle of that window that installed the timer to its message queue. The second argument should be an ID in case you were using more than one timer. The g_timer1 is a pointer which actually was a bad event ID but might work nevertheless ... if you had provided the same ID with SetTimer. But there the event ID was 1 (what could work but surely is not a good choice for a timer installed by a hook).
0
 
itsmeandnobodyelseCommented:
FYI: timers installed by SetTimer are not very accurate cause they were only evaluated at idle times from message bump. A timer installed by a hook has the disadvantage that you probably have difficulties to find out whether the current window you were hooked in, actually runs the main message loop, or only belongs to a modal dialog window, e. g. by a message box currently opened. In the latter case all timer actions may address the wrong target.

You better create a thread with the timer function as thread function and which was waiting 200 milliseconds before running:

void timerThread(void * par)
{
    Sleep(200);

     // if coming here about 200 msec were gone
     dowhatmustbedone(par);

}

The above is a one-time timer which is not dependent on message loops and window processing. you would call it like

  HANDLE hdl = _beginthread(timerThread, 0, this);

and the only thing to care for is that the pointer passed lives longer than the thread.
0
 
ZoppoCommented:
@itsmeandnobodyelse - I'm not sure if you're statement is correct:
> The first argument is the hwnd of the window that runs the message queue. It actually shouldn't be NULL ...

In MSDN for '::SetTimer' it's tells that 'If the function succeeds and the hWnd parameter is NULL, the return value is an integer identifying the new timer. An application can pass this value to the KillTimer function to destroy the timer.' and 'If the hWnd parameter is NULL, and the nIDEvent does not match an existing timer then it is ignored and a new timer ID is generated.'

ZOPPO
0
 
itsmeandnobodyelseCommented:
The main error is that the second argument in KillTimer isn't the eventId you passed with the SetTimer.

The hwnd argument may work with NULL as well but I wouldn't do it with NULL cause the hwnd determines the message queue where the timer is handled. Especially in a hook you shouldn't have a problem to pass the window handle of the current window you were hooked in.
0
 
ZoppoCommented:
Sorry, I still don't agree: In MSDN for '::KillTimer' you can find 'If the application calls SetTimer with hWnd set to NULL, this parameter must be the timer identifier returned by SetTimer.'

As far as I understand this you can either pass a none-NULL HWND to SetTimer or pass NULL as HWND and a pointer to a TimerProc-callback function as fourth parameter. In the first case WM_TIMER messages are sent to the passed window, in the other case the callback function is called.

So I can't see an error there.

@VapiSoft: Unfortunateley I have absoluteley no experience in using timers within hooks. But could you explain a little bit more detailed what kind of hook it is, if it's a global hook or a process-local hook. Is the SetTimer called outside or within the hook-procedure? Could it be that even the SetTimer is called continuously?

ZOPPO
0
 
AndyAinscowFreelance programmer / ConsultantCommented:
@itsmeandnobodyelse.
Note there is a
gtimer1 - function
and
g_timer1 - variable
being used.  I think you missed the underscore
0
 
itsmeandnobodyelseCommented:
>>>> If the function succeeds and the hWnd parameter is NULL, the return value is an integer identifying the new timer

You are right. The docs do describe the way you coded. But I doubt that it could work in your case as the main condition for a timer created by SetTimer is the existence of a message queue. If no window is associated with the timer you would need to run the message pump from your thread. Look at the Remarks section of the MSDN article which says

------------------------
... When you specify a TimerProc callback function, the default window procedure calls the callback function when it processes WM_TIMER. Therefore, you need to dispatch messages in the calling thread, even when you use TimerProc instead of processing WM_TIMER.
------------------------







0
 
itsmeandnobodyelseCommented:
>>>> I think you missed the underscore
Yes, I didn't read the code thoroughly.

>>>> g_timer1=::SetTimer(NULL,1,200,gTimer1);

if the g_timer1 is a global variable defined in the hook.dll, it probably isn't available in the timer function as the latter runs in the context of the hooked process. Hence, the timer proc would read a different value from the variable than being assigned when the SetTimer was called.

If that was true, you could/should replace the global variable by a function provided with the dll like

unsigned int& g_timerId()
{
    static unsigned int timerId = 0;
    return timerId;
}

which then could be used instead of the global variable:

   g_timerId() = SetTimer(NULL,1,200,gTimer1);

and

   KillTimer(NULL, g_timerId());


Note, the above wouldn't work if the SetTimer was called more than once. You could prevent a duplicate SetTimer call by

  if (g_timerId() == 0)
      g_timerId() = SetTimer(NULL,1,200,gTimer1);

and

   KillTimer(NULL, g_timerId());
   g_timerId() = 0;


0
 
VapiSoftAuthor Commented:
I found the problem.
The bug was that it entered the SetTimer twice before it entered the timer procedur.
Therefore the first g_timer1 was overwritten by the second timer.
When it Killed it killed only the second timer because it did not have the g_timer1 of the first time.
Thanks to you all.
0
 
VapiSoftAuthor Commented:
As I wrote, I found the problem which was my mistake.
But I apperciate the help and good will from all the experts.
0

Featured Post

Free Tool: Site Down Detector

Helpful to verify reports of your own downtime, or to double check a downed website you are trying to access.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 5
  • 3
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now