Anandthirtha
asked on
How to get idle/inactive time of application / exe program running on PC?
Requirement is to kill the program if particular application/exe is idle/inactive (not in use) for 20 minutes. I’m able to kill the process but how to get the idle time? I’m coding in Visual Basic 6.0. Please help me out if you’ve some code or suggestions.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Exactly -> ("Check if an Application is Idle for a Period of Time") http://www.freevbcode.com/ShowCode.Asp?ID=3297
>>
Exactly -> ("Check if an Application is Idle for a Period of Time") http://www.freevbcode.com/ShowCode.Asp?ID=3297
<<
Yikes whatever you do don't use this. Slap the code in a form and fire it up. Open up task manager and see how much idle time your CPU doesn't have while the app 'Idles'.
Anthony.
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Sub CheckInputIdle(ByVal TimeOut_InSec As Long)
Dim t As Long
t = Timer
Do While bCancel = False
If GetQueueStatus(QS_INPUT) Then
t = Timer
End If
DoEvents
If Timer - t >= TimeOut_InSec Then Exit Do
Sleep 200
Loop
If bCancel = False Then MsgBox "Process idle is for " & Timer - t & " sec."
End Sub
Public Sub CheckInputIdle(ByVal TimeOut_InSec As Long)
Dim t As Long
t = Timer
Do While bCancel = False
If GetQueueStatus(QS_INPUT) Then
t = Timer
End If
DoEvents
If Timer - t >= TimeOut_InSec Then Exit Do
Sleep 200
Loop
If bCancel = False Then MsgBox "Process idle is for " & Timer - t & " sec."
End Sub
Now try using a real app with that loop in place and you'll find that it's response is sluggish.
DoEvents loops are evil. Avoid as much as possible. Definitely don't use one that last for the entire lifetime of your application.
Anthony.
DoEvents loops are evil. Avoid as much as possible. Definitely don't use one that last for the entire lifetime of your application.
Anthony.
Hello Anthony
Actually, GetQueueStatus is standard API way to determine idle status of a window. Thre is WindowProc main message loop in all other languages except VB, where GetQueueStatus can be placed. I tried to simplify this one for VB. For correct (non-simplified) using you have to subclass window and put this api function inside WinProc callback (without Do...Loop cicle, of course :).
Actually, GetQueueStatus is standard API way to determine idle status of a window. Thre is WindowProc main message loop in all other languages except VB, where GetQueueStatus can be placed. I tried to simplify this one for VB. For correct (non-simplified) using you have to subclass window and put this api function inside WinProc callback (without Do...Loop cicle, of course :).
PS - quick searching over the net gave me this sample:
http://thecodeproject.com/dialog/idledialog.asp
http://thecodeproject.com/dialog/idledialog.asp
Ark,
In order for GetQueueStatus to be used in this way you would have to be in a WindowProc to be guaranteed to see all Input messages. You would also have to sub-class ALL the applications windows and by 'windows' I mean to mean anything with a windowproc not just each form instance.
Sub-classing windows (whilst at times is useful) is best avoided if there is another way to accomplish the same thing. Frankly if you have to sub-class every window then VB just isn't the language to be using. The links you posted rely on code running continuously while the application is 'idle'. This simply isn't a good idea (standard or not).
The code I posted doesn't require a Do Events loop, wierd sub-classing code or putting the thread to sleep and is very lightwieght on the processor.
Anthony.
In order for GetQueueStatus to be used in this way you would have to be in a WindowProc to be guaranteed to see all Input messages. You would also have to sub-class ALL the applications windows and by 'windows' I mean to mean anything with a windowproc not just each form instance.
Sub-classing windows (whilst at times is useful) is best avoided if there is another way to accomplish the same thing. Frankly if you have to sub-class every window then VB just isn't the language to be using. The links you posted rely on code running continuously while the application is 'idle'. This simply isn't a good idea (standard or not).
The code I posted doesn't require a Do Events loop, wierd sub-classing code or putting the thread to sleep and is very lightwieght on the processor.
Anthony.
Know it's not my question, but Anthony your missing a sub or function "ApiRaiseIfNull"
It does look a good answer :) I'm looking forward to seeing the rest, just wish you didn't destroy other peoples confidence when evaluating others' answers:$
Another minor problem is when the program stops running, as I move the mouse and keyboard the VB6 titebar flashes between "design" and what appears to be "running"...might be related to the ApiRaiseIfNull missing though
Matt
It does look a good answer :) I'm looking forward to seeing the rest, just wish you didn't destroy other peoples confidence when evaluating others' answers:$
Another minor problem is when the program stops running, as I move the mouse and keyboard the VB6 titebar flashes between "design" and what appears to be "running"...might be related to the ApiRaiseIfNull missing though
Matt
Matt,
Should have taken out the ApiRaiseIfNull it is part of my Error handling infrastructure and not necessary for the point being demonstrated.
This would do.
Public Sub IdleUnhook()
UnhookWindowsHookEx mhMouseHook
UnhookWindowsHookEx mhKeyboardHook
End Sub
As to destorying other peoples confidence I do have the bad habit of responding impulsive but light heartedly to bad advice. :( Problem is text loses some of the spirit in which some comments are ment. Still bad advice is bad advice and I feel it would be worse to say nothing at all. I may not have the social skills to convey that in the most tactful manner but most people aren't here for pleasent evenings of conversation anyway.
As to the titlebar flashing, this is the sort of thing you probably don't want running in an IDE session. I use the following code to detect that the code is running in an IDE:-
Public mbInDesign as Boolean
Public Sub Main()
SetInDesign
End Sub
Private Function SetInDesign() As Boolean
Static nCallCount As Integer
nCallCount = nCallCount + 1
Select Case nCallCount
Case 1: Debug.Assert SetInDesign()
Case 2: mbInDesign = True
End Select
nCallCount = 0
SetInDesign = True
End Function
In the form load add:-
If mbInDesign then IdleHook
and the form unload:-
If mbInDesign Then IdleUnhook
Anthony.
Should have taken out the ApiRaiseIfNull it is part of my Error handling infrastructure and not necessary for the point being demonstrated.
This would do.
Public Sub IdleUnhook()
UnhookWindowsHookEx mhMouseHook
UnhookWindowsHookEx mhKeyboardHook
End Sub
As to destorying other peoples confidence I do have the bad habit of responding impulsive but light heartedly to bad advice. :( Problem is text loses some of the spirit in which some comments are ment. Still bad advice is bad advice and I feel it would be worse to say nothing at all. I may not have the social skills to convey that in the most tactful manner but most people aren't here for pleasent evenings of conversation anyway.
As to the titlebar flashing, this is the sort of thing you probably don't want running in an IDE session. I use the following code to detect that the code is running in an IDE:-
Public mbInDesign as Boolean
Public Sub Main()
SetInDesign
End Sub
Private Function SetInDesign() As Boolean
Static nCallCount As Integer
nCallCount = nCallCount + 1
Select Case nCallCount
Case 1: Debug.Assert SetInDesign()
Case 2: mbInDesign = True
End Select
nCallCount = 0
SetInDesign = True
End Function
In the form load add:-
If mbInDesign then IdleHook
and the form unload:-
If mbInDesign Then IdleUnhook
Anthony.
I enjoy the pleasent conversations, but then again i'm 17 and don't have a job resting on any of this advice, so what do I know :P...
It looks like this question will probably hit EE cleanup, but whichever answer I find to be the best, I can vouch for as an unbiased impartial person :P
I'm trying to add an idle routine to a chat program that should notify the client when the user is away, sort of how MSN Messenger does it.
Will check your code when I come home again from school
It looks like this question will probably hit EE cleanup, but whichever answer I find to be the best, I can vouch for as an unbiased impartial person :P
I'm trying to add an idle routine to a chat program that should notify the client when the user is away, sort of how MSN Messenger does it.
Will check your code when I come home again from school
' Module idle timing
Private Declare Function SetWindowsHookEx Lib "user32.dll" Alias "SetWindowsHookExA" (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long
Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hHook As Long) As Long
Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal hHook As Long, ByVal ncode As Long, ByVal wParam As Long, lParam As Any) As Long
Private Const WH_KEYBOARD As Long = 2
Private Const WH_MOUSE As Long = 7
Public Sub IdleHook()
mhMouseHook = SetWindowsHookEx(WH_MOUSE,
mhKeyboardHook = SetWindowsHookEx(WH_KEYBOA
End Sub
Public Sub IdleUnhook()
ApiRaiseIfNull UnhookWindowsHookEx(mhMous
ApiRaiseIfNull UnhookWindowsHookEx(mhKeyb
End Sub
'--- Api Callbacks ---
Private Function Mouse_IO(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Mouse_IO = CallNextHookEx(mhMouseHook
mlIdleTime = 0 'we've had activity, so reset ticks
End Function
Private Function Keyboard_IO(ByVal nCode As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Keyboard_IO = CallNextHookEx(mhKeyboardH
mlIdleTime = 0
End Function
Public Function IncrementIdleTime() as Long
mlIdleTime = mlIdleTime + 1
IncrementIdleTime = mlIdleTime
End Function
Now on your main form add a timer 'tmrIdle' give it an interval of say 5000 milliseconds
In the form load add:-
IdleHook
and the form unload:-
IdleUnhook
and add the sub
Private Sub tmrIdle_Timer()
Dim lTicks as Long
lTicks = IncrementIdleTime
If lTicks > 240 Then
' do stuff when idle detected
End If
End Sub
Anthony