Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Find time since last user input in VB .NET

Posted on 2009-05-14
14
Medium Priority
?
599 Views
Last Modified: 2013-11-25
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
Comment
Question by:jes12345
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
14 Comments
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 24389599
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 24389672
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
 

Author Comment

by:jes12345
ID: 24390028
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
Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 2000 total points
ID: 24390898
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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 24390907
If I understand correctly, this only applies to your application; it is not system wide.
0
 

Author Comment

by:jes12345
ID: 24392760
Sorry kaufmed but I did not understand your last question. Can I please ask you to elaborate?
Thanks J
0
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 2000 total points
ID: 24394476
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
 

Author Comment

by:jes12345
ID: 24395221
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
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 24395534
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
 

Author Comment

by:jes12345
ID: 24401488
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
 
LVL 75

Accepted Solution

by:
käµfm³d   👽 earned 2000 total points
ID: 24404378
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
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 2000 total points
ID: 24404382
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
 

Author Comment

by:jes12345
ID: 24405308
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
 

Author Closing Comment

by:jes12345
ID: 31581695
Good answer!
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever wanted to restrict the users input in a textbox to numbers, and while doing that make sure that they can't 'cheat' by pasting in non-numeric text? Of course you can do that with code you write yourself but it's tedious and error-prone …
If you have ever used Microsoft Word then you know that it has a good spell checker and it may have occurred to you that the ability to check spelling might be a nice piece of functionality to add to certain applications of yours. Well the code that…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
Suggested Courses

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question