2008-10-15 4 views
9

Divers programmes ne peuvent effectuer des tâches que lorsque vous n'avez pas utilisé l'ordinateur pendant un certain temps (économiseur d'écran, indexation Google Desktop, etc.). Comment peuvent-ils savoir quand ils ont été inactifs?Comment savoir quand Windows est inactif

Y a-t-il une fonction dans Windows qui vous indique depuis combien de temps il est inactif, ou devez-vous utiliser une sorte de hook clavier/souris pour suivre vous-même l'activité?

J'utilise C#, mais je suis intéressé par toute méthode de détermination de l'inactivité.

Répondre

10

EDIT: a changé la réponse, fournissant le texte et les détails derrière la réponse de Shy (qui devrait être et a été acceptée). N'hésitez pas à fusionner et supprimer celui-ci.

GetLastInputInfo La fonction GetLastInputInfo récupère l'heure du dernier événement d'entrée.

Collé ici de P/Invoke

Cette fonction récupère le temps écoulé depuis la dernière entrée utilisateur

[DllImport("user32.dll")] 
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); 

static int GetLastInputTime() 
{ 
    int idleTime = 0; 
    LASTINPUTINFO lastInputInfo = new LASTINPUTINFO(); 
    lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo); 
    lastInputInfo.dwTime = 0; 

    int envTicks = Environment.TickCount; 

    if(GetLastInputInfo(ref lastInputInfo)) 
    { 
    int lastInputTick = lastInputInfo.dwTime; 

    idleTime = envTicks - lastInputTick; 
    } 

    return ((idleTime > 0) ? (idleTime/1000) : idleTime); 
} 

[StructLayout(LayoutKind.Sequential)] 
struct LASTINPUTINFO 
{ 
    public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); 

    [MarshalAs(UnmanagedType.U4)] 
    public int cbSize;  
    [MarshalAs(UnmanagedType.U4)] 
    public UInt32 dwTime; 
} 

FWIW: Je mis en place un crochet du clavier global et de la souris pendant AnAppADay. Voir cette application pour la source - il est assez proche de ce que vous voulez. Les classes que vous voulez sont dans l'espace de noms AnAppADay.Utils. [rayé en raison de linkrot]

+0

Notez que la valeur int retournée est une valeur en secondes, qui n'est pas immédiatement claire ci-dessus. (Personnellement, j'appellerais la fonction SecondsSinceLastInput ou similaire) – Gareth

+0

Je l'ai fait ensuite utilisé psexec pour l'envoyer à une machine distante à mon collègue. Il montre plus de 2000 secondes et augmente. Et je le vois utiliser son ordinateur, donc c'est trompeur. Il semble montrer plutôt le temps depuis que la machine a été allumée. – fjleon

5

Google is your friend

utilise essentiellement this.
n'oubliez pas tout à fait prêt à la documentation avant d'utiliser.

+0

Je recherchais "inactif" vs "inactif". GetLastInputInfo est exactement ce dont j'avais besoin. Merci. –

+0

Pensez que c'est seulement pour la session en cours. Il peut y avoir d'autres sessions où les utilisateurs sont actifs. Je ne sais pas s'il est possible de faire cette intersession, car cela pourrait constituer une atteinte à la sécurité. – shoosh

+0

Je me demande pourquoi cela a été downvoted? La seule raison que je peux penser est que cela n'a que des liens et aucune réponse réelle? Ou qu'est-ce parce qu'il y a des problèmes avec l'utilisation de GetLastInputInfo? –

0

Les crochets pour clavier et souris sont ce que je trouve le plus précieux. La classe ci-dessous peut être insérée et vous n'avez qu'à comprendre ce que vous voulez faire avec les informations sur les mises à jour de la clé et de la souris.

using System; 
using System.Runtime.InteropServices; 
using System.Threading; 
using System.Windows.Forms; 

namespace Example { 

    public class Hook { 

     delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam); 

     [FlagsAttribute] 
      public enum WindowMessage { 
      WM_KEYDOWN =  0x0000000000000100, // &H100 
      WM_MOUSEMOVE =  0x0000000000000200, // &H200 
      WM_LBUTTONDOWN = 0x0000000000000201, // &H201 
      WM_RBUTTONDOWN = 0x0000000000000204, // &H204 
      WH_KEYBOARD = 2, 
      WH_MOUSE = 7, 
      HC_ACTION = 0 
     } 

     [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
     private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam); 

     [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
     private static extern bool UnhookWindowsHookEx(int idHook); 

     [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)] 
     private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId); 

     //Declare MouseHookProcedure as a HookProc type. 
     static HookProc MouseHookProcedure; 
     static HookProc KeyboardHookProcedure; 

     private static int mhMouseHook = 0; 
     private static int mhKeyboardHook = 0; 

     public Hook() {} 

     public static void Init() { 
      MouseHookProcedure = new HookProc(MouseHookProc); 
      KeyboardHookProcedure = new HookProc(KeyboardHookProc); 
      mhMouseHook = SetWindowsHookEx((int)WindowMessage.WH_MOUSE, MouseHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId()); 
      mhKeyboardHook = SetWindowsHookEx((int)WindowMessage.WH_KEYBOARD, KeyboardHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId()); 
     } 

     public static void Terminate() { 
      UnhookWindowsHookEx(mhMouseHook); 
      UnhookWindowsHookEx(mhKeyboardHook); 
     } 

     private static int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam) { 
      if (nCode >= 0) { 
       //do something here to update the last activity point, i.e. a keystroke was detected so reset our idle timer. 
      } 
      return CallNextHookEx(mhMouseHook, nCode, wParam, lParam); 
     } 

     private static int KeyboardHookProc(int nCode, IntPtr wParam, IntPtr lParam) { 
      if (nCode >= 0) { 
       //do something here to update the last activity point, i.e. a mouse action was detected so reset our idle timer. 
      } 
      return CallNextHookEx(mhKeyboardHook, nCode, wParam, lParam); 
     } 

    } 
} 

Bien sûr, cela ne fonctionne que dans l'application que vous utilisez. Si vous devez suivre l'inactivité sur l'ensemble du système, vous devez créer une DLL qui peut être chargée dans les espaces d'adressage de toutes les autres fenêtres. Malheureusement, je n'ai entendu parler d'aucun hack qui permettrait à un .dll compilé. Net qui fonctionnera dans ce scénario; nous avons une DLL C++ qui s'accroche à cet effet.

+0

Connaissez-vous GetLastInputInfo? Y at-il une raison pour que vous le fassiez à la place de GetLastInputInfo? –

+0

Il est plus complexe ;-) ppl comme ça :) – Skuta

+0

En fait, non, je n'étais pas au courant de GetLastInputInfo. Mais étant donné qu'en général, quand nous faisons ce genre de hooks, nous ne cherchons pas seulement des informations de timeout, cet appel seul ne serait pas utile pour nous. Nous utilisons généralement une plus grande gamme de fonctionnalités de gestion des clés et de la souris. – Bill

Questions connexes