Improve company productivity with a Business Account.Sign Up

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

Find time since last user input in VB .NET

Does anyone know a way to find the time since the last user input (mouse or keyboard). I do not want this to effect system performance so I do not think it is a good idea to capture all user input so I am hoping someone knows about an alternative way. Thanks J
0
jes12345
Asked:
jes12345
  • 8
  • 6
4 Solutions
 
käµfm³d 👽Commented:
0
 
käµfm³d 👽Commented:
VB Translation:
<DllImport("user32.dll")> _
Shared Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
End Function
 
Friend Structure LASTINPUTINFO 
    Public cbSize As UInt;
    Public dwTime As UInt;
End Structure

Open in new window

0
 
jes12345Author Commented:
In order to get it to work I had to put the code in a module. However the objects time is 0 even after the sleep.
Module Module1
    Public Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
    End Function
 
    Friend Structure LASTINPUTINFO
        Public cbSize As Integer
        Public dwTime As Integer
    End Structure
End Module
 
'AND
 
Imports System.Runtime.InteropServices
Imports System.Text
 
Public Class Form1
 
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        System.Threading.Thread.Sleep(15000)
 
        Dim test As New LASTINPUTINFO
        GetLastInputInfo(test)
        MsgBox(test.dwTime)
    End Sub
End Class

Open in new window

0
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.

 
käµfm³d 👽Commented:
I updated the code. It would seem I didn't provide all the information. I tested the following and it returned an integer value.
Imports System.Runtime.InteropServices
 
Module WinAPO
    <DllImport("user32.dll")> _
    Function GetLastInputInfo(ByRef plii As LASTINPUTINFO) As Boolean
    End Function
 
    <StructLayout(LayoutKind.Sequential)> _
    Structure LASTINPUTINFO
        <MarshalAs(UnmanagedType.U4)> _
        Public cbSize As Integer
 
        <MarshalAs(UnmanagedType.U4)> _
        Public dwTime As Integer
    End Structure
 
End Module
 
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        System.Threading.Thread.Sleep(3000)
 
        Dim test As New LASTINPUTINFO
        test.cbSize = Marshal.SizeOf(test)
        test.dwTime = 0
 
        GetLastInputInfo(test)
        MsgBox(test.dwTime)
    End Sub
 
End Class

Open in new window

0
 
käµfm³d 👽Commented:
If I understand correctly, this only applies to your application; it is not system wide.
0
 
jes12345Author Commented:
Sorry kaufmed but I did not understand your last question. Can I please ask you to elaborate?
Thanks J
0
 
käµfm³d 👽Commented:
Do you mean post?

From what I read in the documentation, the GetLastInputInfo() function only tracks the time for input within the application it is being used. So let's say you have your application written and running (and it's using GetLastInputInfo()). If you were to minimize the application and go to something else, while you were in that other application, the GetLastInputInfo() in your application will not track the time in the application you are now using.

--See "Remarks" section
http://msdn.microsoft.com/en-us/library/ms646302(VS.85).aspx
0
 
jes12345Author Commented:
Ok I understand.Thank you for your replies. What I need is really a systemwide function. From reading the article it suggest to create a service using GetLastInputInfo() but that will not be possible on the design. Can you think of any other way of obtaining this? - if not I will find another design approach if installing a service is not an option.
Thanks J
0
 
käµfm³d 👽Commented:
You could implement some low-level hooks in conjunction with a timer. The low-level hooks will intercept the keyboard/mouse interactions and with each interception, you could restart the timer.
0
 
jes12345Author Commented:
I guess that would be an option - do you think this would be ok with regards to system performance? Thank you so much for all your help and advises. Before I close this thread and assign the points can I please ask if you have an example of an efficient way of caturing key/mouse system wide? Thanks J
0
 
käµfm³d 👽Commented:
The only way I know to do it is with API calls. As far as performance, I don't believe it will hit the system that hard--you are intercepting the messages and forwarding them when you are done with them. Now if you do a bunch of processing before you forward the message, then maybe that could hinder your system, but if you are merely determining last input, then I don't see a lot of processing going on before you forward the message.

I can't remember which project I got the following code from, but it was taken from one of the examples on CodeProject.com. There is no mouse hooking in the following, but it should be along the same lines and easy to find on web.
Imports System
Imports System.Diagnostics
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
 
Namespace KeyLogger
 
    Public Class InterceptKeys
        Private Const WH_KEYBOARD_LL As Integer = 13
        Private Const WM_KEYDOWN As Integer = &H100
        Private Const WM_KEYUP As Integer = &H101
        Private Shared _proc As LowLevelKeyboardProc = AddressOf HookCallback
        Private Shared _hookID As IntPtr = IntPtr.Zero
        Private Shared outFile As System.IO.StreamWriter
 
        Public Shared Sub Main()
            _hookID = SetHook(_proc)
            outFile = New System.IO.StreamWriter("C:\out.txt", True)
            outFile.AutoFlush = True
            Application.Run()
            UnhookWindowsHookEx(_hookID)
            outFile.Close()
            outFile = Nothing
        End Sub
 
        Private Shared Function SetHook(ByVal proc As LowLevelKeyboardProc) As IntPtr
            Using curProcess As Process = Process.GetCurrentProcess()
                Using curModule As ProcessModule = curProcess.MainModule
                    Return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0)
                End Using
            End Using
        End Function
 
        Private Delegate Function LowLevelKeyboardProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
 
        Private Shared Function HookCallback(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
            If nCode >= 0 And wParam = CType(WM_KEYDOWN, IntPtr) Then
                Dim vkCode As Integer = Marshal.ReadInt32(lParam)
 
                If vkCode = 13 Then
                    outFile.WriteLine()
                Else
                    outFile.Write((CType(vkCode, Keys).ToString().Replace("Space", " ").Replace("comma", ",").Replace("ControlKey", "^").Replace("Capital", "<CapsLock>").Replace("Back", "<Backspace>")))
                End If
            End If
 
            Return CallNextHookEx(_hookID, nCode, wParam, lParam)
        End Function
 
        <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function SetWindowsHookEx(ByVal idHook As Integer, ByVal lpfn As LowLevelKeyboardProc, ByVal hMod As IntPtr, ByVal dwThreadId As UInteger) As IntPtr
        End Function
 
        <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function UnhookWindowsHookEx(ByVal hhk As IntPtr) As Boolean
        End Function
 
        <DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function CallNextHookEx(ByVal hhk As IntPtr, ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr
        End Function
 
        <DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)> _
        Private Shared Function GetModuleHandle(ByVal lpModuleName As String) As IntPtr
        End Function
 
        <DllImport("user32.dll")> _
        Public Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
        End Function
 
        <DllImport("user32.dll")> _
        Public Shared Function ShowWindow(ByVal hWnd As IntPtr, ByVal nCmdShow As Integer) As Boolean
        End Function
    End Class
End Namespace

Open in new window

0
 
käµfm³d 👽Commented:
I used the above as a key logger on my local machine. I'm sure you could adapt it to suit you needs--I merely wanted to show which API functions (the ones with the DllImport attributes attached) you would need. You could start a timer in HookCallback() to track the time in between inputs.
0
 
jes12345Author Commented:
Fantastic - I will definately be able to use this for my solution. Thank you so much for all your advises and help kaufmed! J
0
 
jes12345Author Commented:
Good answer!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 8
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now