0

I have a main form that I load and when 20 minutes have passed I want a login form to open for security reasons. I want to verify that the proper user is using the software so I have thought about using a timer and give the timer an interval of 20 minutes. This is my code:

private void timer1_Tick_1(object sender, EventArgs e)
{
    foreach (Form f in Application.OpenForms)
    {
        if (f.Name != "login2")
        {
            login2 lss = new login2();
            lss.ShowDialog(); 
        } 
    }
}

The problem here is that it opens the form every 20 minutes. This means that if the user is not doing anything, it is just showing one login form after another, causing multiple login forms to appear, which I do not want. I have used the loop but it still do not get it working properly. I do not know why.

apart from this can I implement the function that if the form is idle for 20 mints then show the login form and id not idle then don't show the login form?? is it easy to implement? I don't want any complication as I am a new comer to c# doing first time

BenMorel
  • 34,448
  • 50
  • 182
  • 322
shariq_khan
  • 671
  • 4
  • 16
  • 33
  • 2
    Your users aren't going to like you. Not at all! – Nick Butler Jan 13 '13 at 13:04
  • why so? i first thought that if the software is idle for 20 mints then it will show the login form but how can i implement this so i thougt about timer. can you suggest how can i implement that is the form is idle for 20 mints then show login form? is it easy? – shariq_khan Jan 13 '13 at 13:07
  • 1
    So every time a user comes back to your app, they will have to log in again? That's going to get old real quick. Is it really necessary? Unless you're writing the controller for global thermonuclear war... probably not. – Nick Butler Jan 13 '13 at 13:13
  • sir i want that for my need. can you help me now? – shariq_khan Jan 13 '13 at 13:14
  • okay i deleted my answer. here the related topic which is fit to your problem http://stackoverflow.com/questions/1541981/check-if-an-application-is-idle-for-a-time-period-and-lock-it – spajce Jan 13 '13 at 14:00

2 Answers2

1

If what you're looking for is to effectively log the user out of your application (or at least give the appearance of being logged out) after a period of inactivity, then you can p/invoke GetLastInputInfo to meet your requirements.

Within your Timer tick event, you can use GetLastInputInfo to return you the last time any user input was detected. Subtracting this from Environment.TickCount will give you the period of inactivity. If it meets your criteria for logging a user out, then you can display your login form.

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

[StructLayout(LayoutKind.Sequential)]
internal struct LASTINPUTINFO
{
    public uint cbSize;
    public uint dwTime;
}

private void timer1_Tick_1(object sender, EventArgs e)
{
    var lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);

    GetLastInputInfo(ref lastInputInfo);

    int inactivityThreshold = 20 * 60 * 1000;

    if ((Environment.TickCount - lastInputInfo.dwTime) > inactivityThreshold)
    {
        login2 lss = new login2();
        lss.ShowDialog(); 
    } 
}

To solve your problem with form appearing more than once, just use a boolean to indicate whether you are currently logging the user in and use it as part of your criteria as to whether you show your login form or not.

thudbutt
  • 1,481
  • 1
  • 19
  • 32
  • sir can you explain the getlastinput info. i have never heard it of. can you give me some example? please is you can – shariq_khan Jan 13 '13 at 13:50
  • You can see an example of it in use here: http://joelabrahamsson.com/entry/detecting-mouse-and-keyboard-input-with-net I will add the basics to my answer so it's included on SO. – thudbutt Jan 13 '13 at 13:59
1

First, add a function to reset your timer:

private void ResetTimer()
{
    timer1.Stop();
    timer1.Start();
}

When called, it will reset the timer.

Second, to avoid having multiple dialogs opening, use the same instance. Add instance of that login form as a class member then use it instead of creating new one every time:

login2 lss = new login2();
private void timer1_Tick(object sender, EventArgs e)
{
    if (!lss.Visible)
    {
        lss.ShowDialog();
        ResetTimer();
    }
}

As you can see, it will call the dialog and only when it's not already visible to avoid errror. It also reset the timer after user exit the dialog.

Finally, to have it count down only when "idle", you need to reset the timer whenver there is any action. The simple case is mouse move and key press for every control in your form:

this.Controls.Cast<Control>().ToList().ForEach(c =>
{
    c.MouseMove += (s1, e1) => ResetTimer();
    c.KeyPress += (s1, e1) => ResetTimer();
});

When inside your main form's Load event this will assign the event handler for all controls, but if you have nested controls you'll have to use recursion to get them all.

Shadow The GPT Wizard
  • 66,030
  • 26
  • 140
  • 208
  • thank you sir, and what is the last part can you explain? which is this.controls and all the thing? is it linq? – shariq_khan Jan 13 '13 at 14:14
  • Yes it's Lambda expression to save the need of creating new methods. – Shadow The GPT Wizard Jan 13 '13 at 14:15
  • c.MouseMove += (s1, e1) => ResetTimer(); i heard that by the left side of lamda expression there is input and the other side there is output... can you tell me why is the s1 and e1 is given input to the timer as the method doest not take any argument? – shariq_khan Jan 13 '13 at 14:25
  • 1
    It's just a shorthand way to declare anonymous delegates. `s1` and `e1` are the parameters of the anonymous function that is created behind the scenes, they are both necessary because the signature of the event handlers requires two parameters but you don't have to use them. :) – Shadow The GPT Wizard Jan 13 '13 at 14:33