2

Is there a way to detect whether a Windows process is idle?

idle Means, when a particular application's process is not processing anything(The application is waiting for userinput).

cheers

paktrick
  • 71
  • 1
  • 4
  • What do you mean with user input? Is it a commandline application blocking on getc(), or do you mean a GUI application doing nothing but waiting until a button is pressed? – Bart Aug 03 '11 at 11:14
  • possible duplicate of [How to detect when a process/ thread is waiting for user input](http://stackoverflow.com/questions/6911498/how-to-detect-when-a-process-thread-is-waiting-for-user-input) – Hasturkun Aug 03 '11 at 13:46
  • hey bart, Exactly that "Gui application doing nothing but waiting until a button is pressed" – paktrick Aug 03 '11 at 13:47
  • That would require explicit of knowledge of that monitored application. The fact it's showing a button doesn't equate to "idle" (a Cancel button, for example). Perhaps just use the SetWindowHook as @cprogrammer suggests and monitor the button and controls you want to know about. – noelicus Aug 03 '11 at 14:52

3 Answers3

1

You can put a hook SetWindowsHookEx with WH_FOREGROUNDIDLE

cprogrammer
  • 5,503
  • 3
  • 36
  • 56
  • Hey cProgramming thanks for quick replay, i currently have a HWND, how can i hook the HWND to windowHookex? – paktrick Aug 03 '11 at 11:15
  • You should tell us more about your application. SetWindowsHookEx can be put on a thread but if you have a HWND there are other ways to handle this. Like SetWindowLong with GWL_WNDPROC and see when you are not receiving messages or if you are using MFC there is a message named WM_KICKIDLE which is a message that MFC sends whenever a dialog is idle. – cprogrammer Aug 03 '11 at 11:24
  • I'll try re-phrase that. Using an installation of a application as an example: - User runs setup.exe, then enters some settings (to configure program), after this there will be some point in which the program will begin to install. When the program has finished, its process should be idle rite? waiting for user input, this is what i'm trying to figure out. – paktrick Aug 03 '11 at 11:28
  • are you inside the process ? it's a console or a gui app ? – cprogrammer Aug 03 '11 at 11:32
  • Gui App, I was gonna use GetForegroundWindow to obtain the handle and get its process id, with that somehow detect when its idle – paktrick Aug 03 '11 at 11:35
  • GetForegroundWindow -> GetWindowThreadProcessId -> SetWindowsHookEx – cprogrammer Aug 03 '11 at 11:43
0

If you mean you want to detect if the application is happy and receiving messages (user input) check the return of this function:

SendMessageTimeout(HwndInQuestion, WM_NULL, 0, 0, SMTO_ABORTIFHUNG, 10);

Just set the timeout (10ms in the example) to what you think is sensible for your use.

noelicus
  • 14,468
  • 3
  • 92
  • 111
0

A short summary of what I found about this topic for the MFC case where you want to be notified whenever the process is idle (do some background work etc.) but not in a polling/ waiting fashion

(variable names are suggestions):

-> If its an MFC application without modal dialogs:

add ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI,OnIdleUpdateCmdUI) to message map together
with the method afx_msg void OnIdleUpdateCmdUI()

-> If its a dialog within a MFC application:

add ON_MESSAGE(WM_KICKIDLE, OnKickIdle) to message map together 
with the method afx_msg LRESULT OnKickIdle(WPARAM wParam, LPARAM lParam);

-> If you want both (application & dialogs):

.) add a public member variable to the main frame (also a static global variable is possible)

HOOKPROC m_detectIdleHook

.) add method prototype to the main frame's header file

friend LRESULT CALLBACK OnForeGroundIdle( int nCode, WPARAM wParam, LPARAM lParam )

with this content (note that it is not a member function of the main frame!)

LRESULT CALLBACK OnForeGroundIdle( int nCode, WPARAM wParam, LPARAM lParam )
{   
    // Do/check stuff in idle time here
    return ::CallNextHookEx( (HHOOK)((CMyMainFrame*)AfxGetMainWnd())->m_detectIdleHook, nCode, wParam, lParam );
}

.) set the window hook at the end of the main frame ::OnCreate

m_detectIdleHook = (HOOKPROC)SetWindowsHookEx( WH_FOREGROUNDIDLE, 
                                         OnForeGroundIdle,
                                         NULL,
                                         ::GetCurrentThreadId());

.) At the end when you are finished, unhook the window in the main frame deconstructor

UnhookWindowsHookEx((HHOOK)m_detectIdleHook);

None of these solutions will work if the application is not active (another application has the focus). The only solution I see here is to use a WM_TIMER and to check the idle state by WaitForInputIdle (http://msdn.microsoft.com/en-us/library/ms687022%28VS.85%29.aspx) but this would introduce a certain polling interval dependability.

Sources:

-This page

-http://www.drdobbs.com/184416462

-http://www.codeguru.com/forum/showthread.php?t=199148

-http://www.codeproject.com/KB/dialog/idledialog.aspx?msg=770930

Oliver Zendel
  • 2,695
  • 34
  • 29
  • p.s. It looks like this topic gets a lot more difficult in vista/win7 as the SetWindowsHookEx apparently needs a high privilege (UAC). – Oliver Zendel Mar 16 '12 at 08:59