(Print this page)

Automatically close an application when inactive
Published date: Sunday, June 22, 2008
On: Moer and Éric Moreau's web site

Somebody posted a question in a newsgroup lately about how he could detect an inactive user in his application. He wanted to kill the application after 10 minutes of inactivity. That remembered me something I did a long time ago (in the VB6 era) and discovered that the approach might still be valid!

Keeping track of the active form and control

When I first thought to the possible solutions, I remembered an old VB5/6 application that needed to shut down every night. To enable this feature, I was keeping track of the active form and active control every 30 seconds. If one of these 2 was modified then that was meaning that the user was still using the application and I was resetting a variable. If nothing was modified for 5 minutes, I simply shut down the application.

This method is still valid using .Net.

The required code

This code is very simple. Every time the timer triggers the Tick event (every second in the demo application but should be longer in a real application no to use too much resources), you need to check the current form and the current control. You could also check the value but then you would need to compare different properties based on the control class (ie: Text for a TextBox, Checked for a CheckBox ...).

I have created a form that contains the Timer control, that is doing all the comparison and which terminates the application if required. This form is named fTimer1.

To retain the active form and control name, I declare static variables. If you are not familiar with them, you may think of them as having the same scope as a class level member (they will exist and keep their value as long as the instance of the class is in memory) but is only visible from within the method in which they are declared. So here is the variables’ declaration:

Static sstrPreviousForm As String = String.Empty
Static sstrPreviousControl As String = String.Empty
Static sdtmLastAction As DateTime
To retrieve current form’s and control’s name, you may use this code:
Dim strCurrentForm As String
If ActiveForm IsNot Nothing Then
    strCurrentForm = ActiveForm.Name
Else
    strCurrentForm = String.Empty
End If

Dim strCurrentControl As String
If ActiveForm IsNot Nothing AndAlso ActiveForm.ActiveControl IsNot Nothing Then
    strCurrentControl = ActiveForm.ActiveControl.Name
Else
    strCurrentControl = String.Empty
End If
I have discovered while testing that the ActiveForm object value is set to Nothing when another application is having the focus. This doesn’t affect our logic.

We now have everything to compare current and previous values using this code:

If (strCurrentForm <> sstrPreviousForm) OrElse (strCurrentControl <> sstrPreviousControl) Then
    sstrPreviousForm = strCurrentForm
    sstrPreviousControl = strCurrentControl
    sdtmLastAction = Date.Now
    Label1.Text = sstrPreviousForm
    Label2.Text = sstrPreviousControl
End If
If something has changed, we keep the current values into the Static variables for the next comparison. We also set a Static DateTime variable to the current time to be able to calculate the amount of time that the user didn’t worked with our application.

We are now ready to calculate the elapsed time since the last time an action was detected. The DateDiff method is the easiest way to handle that task. This method requires that you pass an interval (the unit used for the calculation, ie: seconds, minutes, days, months ...) and the 2 dates to on which you want to do the calculation. In my case, I wanted the result to be calculated in seconds:

Dim intSeconds As Int64 = DateDiff(DateInterval.Second, sdtmLastAction, Date.Now)
For testing purposes, I then display the number of seconds:
Label3.Text = intSeconds.ToString + " seconds since last activity detected."
Finally, we exit the application if this number of seconds is greater than the inactivity period you allow (replace 30 with the number of seconds you want to allow):
If intSeconds > 30 Then Application.Exit()
In my old VB5/6 application, I was only exiting the application if the current time was somewhere between 8PM and 6AM.

Using the timer form

The last thing you want to do is to put this logic into each form your application contains. That’s why the timer form should be self contained. You only need to load it once in an application. For example, your main form can load a new instance of this form like this (its Load event is a good place):

Dim x As New fTimer1
As soon as this line has been executed, the timer starts (if it is enabled) and your application will exit if you do nothing with the application for the number of seconds you have set (even if you work with other any application on your PC).

For testing/debugging purposes, you can also make the timer form visible (but it is not required to have it working properly):

x.Show()

Figure 1: The demo application in action

The Application’s Idle event

After I have completed the previous example, I remembered that the Application object provides an Idle event. After a quick test, I was convinced that it wasn’t really good for me. In the downloadable demo, I have provided my test forms that are using this event and I have never been able to get it to work properly. If you find a way, drop me a note!

Conclusion

I thought that this feature could be helpful for some of you.

I hope you appreciated the topic and see you next month.


(Print this page)