How to close out Access when a computer is locked?

Collapse
X
 
  • Time
  • Show
Clear All
new posts

  • NeoPa
    replied
    Sorry for the delay responding.

    I think your idea is actually a very good one. There is a potential loophole there if an operator is continually working on data on the same form (particularly if there are only a few controls on it).

    After line #29 you can add an If statement just like the preceeding ones that checks for Err = 438 and sets that variable (ActiveControlVa lue) to either a specific string or possibly even Null. That should work nicely for you.

    Leave a comment:


  • Endkill Emanon
    replied
    Logging out the user/customer(CX) gets them out of the database thus unlocking it and allowing others to get into it. I've had 3 different jobs where I've had at times to log someone off so that other CX can use a file or database.

    Also If I remember correctly there's a way using ASP to interface the db. You could create a web-app this way and the only thing that has it locked is the server hosting it.

    Leave a comment:


  • normalice
    replied
    thanks again, NeoPa.

    I haven't actually tried this yet, but I was wondering about a specific situation: if the active control is a button. Buttons don't have a value, but since the activecontrolna me doesn't throw an error, it will try to save the activecontrolva lue - but attempting to do so on a button should throw an error, i think? Wouldn't erroring during the attempt to write the activecontrolva lue cause problems in the if statement that controls recording and resetting - thus causing the database to never close if a button remains the active control?

    ...

    Okay, i tried it. the error it throws when a button is selected it 438. I'll just add that after the write and it'll be fine.

    Thanks again for all your help!
    Last edited by normalice; Dec 21 '10, 02:45 PM. Reason: after testing...

    Leave a comment:


  • NeoPa
    replied
    Originally posted by Endkill Emanon
    Endkill Emanon:
    This is simple if you have a network admin account. You ether go to or remote into the offending computer. Then log-out the person using the admin account. They'll lose their work but you'll get your DB back.
    I'm not sure what you're trying to say exactly, but the question was specifically asking about closing down when the database was idle. Kicking a user off would not fall into that category.

    Leave a comment:


  • NeoPa
    replied
    That's actually quite good thinking. A user may well stay in the same control and still be active. I like that.

    You've made a pretty good stab at it I would say, but you probably want to treat the .Value as a Variant type, rather than as a String specifically. I've made some changes to your code, but not highlighted where they are. You'll need to copy and paste the whole lot.

    Code:
    Option Compare Database
    Option Explicit
    
    ' conIdleThreshold determines how much idle time to wait
    ' for before running the IdleTimeDetected subroutine.
    Private Const conIdleThreshold As Long = 5 * 60& * 1000&
    
    Private PrevControlName As String
    Private PrevFormName As String
    Private ExpiredTime As Long
    Private PrevControlValue as Variant
    
    Private Sub Form_Timer()
        Dim ActiveFormName As String
        Dim ActiveControlName As String
        Dim ActiveControlValue as Variant
    
        On Error Resume Next
    
        ' Get the active form and control name.
        With Screen
            ActiveFormName = .ActiveForm.Name
            If Err = 2475 Then ActiveFormName = "No Active Form"
            ActiveControlName = .ActiveControl.Name
            If Err = 2474 Then
                ActiveControlName = "No Active Control"
                ActiveControlValue = Null
            Else
                ActiveControlValue = .ActiveControl.Value
            End If
        End With
    
        ' Record the current active names and reset ExpiredTime if:
        '    1. They have not been recorded yet (code is running
        '       for the first time).
        '    2. The previous names are different from the current ones
        '       (the user has done something different during the timer
        '        interval).
        If (PrevControlName = "") _
        Or (PrevFormName = "") _
        Or (IsNull(PrevControlValue)) _
        Or (ActiveFormName <> PrevFormName) _
        Or (ActiveControlName <> PrevControlName) _
        Or (ActiveControlValue <> PrevControlValue) Then
            PrevControlName = ActiveControlName
            PrevFormName = ActiveFormName
            PrevControlValue = ActiveControlValue
            ExpiredTime = 0
        Else
            ' ...otherwise the user was idle during the time interval, so
            ' increment the total expired time.
            ExpiredTime = ExpiredTime + Me.TimerInterval
        End If
    
        ' Does the total expired time exceed the conIdleThreshold?
        If ExpiredTime >= conIdleThreshold Then
            ' ...if so, then reset the expired time to zero...
            ExpiredTime = 0
            ' ...Clear the timer event...
            Me.TimerInterval = 0
            ' ...and call the IdleTimeDetected subroutine.
            Call MsgBox("Triggered")
        End If
    End Sub

    Leave a comment:


  • Endkill Emanon
    replied
    This is simple if you have a network admin account. You ether go to or remote into the offending computer. Then log-out the person using the admin account. They'll lose their work but you'll get your DB back.
    Last edited by Endkill Emanon; Dec 21 '10, 01:04 AM. Reason: grammer

    Leave a comment:


  • normalice
    replied
    hey, i had a follow-up question, and since I don't really understand some of the code you posted, i figured I should just ask directly.

    In addition to the activecontrolna me and and activeformname I would also like to include the activecontrolva lue: if that changes then also reset the counter.

    I think it would go something like this, but I don't know what the question marks (????) would be. I've underlined the parts I added, and bolded/italicized the part for which I haven't a clue. Of course, the bold doesn't show up so well (the question marks should be a dead giveaway)...
    Code:
    Option Compare Database 
    Option Explicit 
      
    ' conIdleThreshold determines how much idle time to wait 
    ' for before running the IdleTimeDetected subroutine. 
    Private Const conIdleThreshold As Long = 5 * 60& * 1000& 
      
    Private PrevControlName As String 
    Private PrevFormName As String 
    Private ExpiredTime As Long 
    [U]Private PrevControlValue as string[/U]  
    Private Sub Form_Timer() 
        Dim ActiveFormName As String 
        Dim ActiveControlName As String 
        [U]Dim ActiveControlValue as String[/U]
        On Error Resume Next 
      
        ' Get the active form and control name. 
        With Screen 
            ActiveFormName = .ActiveForm.Name 
            If Err = 2475 Then ActiveFormName = "No Active Form" 
            ActiveControlName = .ActiveControl.Name 
            If Err = 2474 Then ActiveControlName = "No Active Control" 
           [U] ActiveControlValue = .ActiveControl.Value[/U]
            [u]If Err = [I][B]????[/B][/I] Then ActiveControlValue = "No Value"[/u]    
    End With 
      
        ' Record the current active names and reset ExpiredTime if: 
        '    1. They have not been recorded yet (code is running 
        '       for the first time). 
        '    2. The previous names are different from the current ones 
        '       (the user has done something different during the timer 
        '        interval). 
        If (PrevControlName = "") _ 
        Or (PrevFormName = "") _ 
        Or (ActiveFormName <> PrevFormName) _ 
        Or (ActiveControlName <> PrevControlName) _
        [U]Or (ActiveControlValue <> PrevControlValue)[/U] Then 
            PrevControlName = ActiveControlName 
            PrevFormName = ActiveFormName
            [U]PrevControlValue = ActiveControlValue[/U]        
            ExpiredTime = 0 
        Else 
            ' ...otherwise the user was idle during the time interval, so 
            ' increment the total expired time. 
            ExpiredTime = ExpiredTime + Me.TimerInterval 
        End If 
      
        ' Does the total expired time exceed the conIdleThreshold? 
        If ExpiredTime >= conIdleThreshold Then 
            ' ...if so, then reset the expired time to zero... 
            ExpiredTime = 0 
            ' ...Clear the timer event... 
            Me.TimerInterval = 0 
            ' ...and call the IdleTimeDetected subroutine. 
            Call MsgBox("Triggered") 
        End If 
    End Sub

    Leave a comment:


  • NeoPa
    replied
    That code was only ever meant for testing. It should work, fundamentally, but it includes a whole bunch of unnecessary lines simply to help me determine what was what.

    Here is a sanitised version, with the MsgBox() call where you would want to put the call to Application.Qui t (or IdleTimeDetecte d()) :
    Code:
    Option Compare Database
    Option Explicit
    
    ' conIdleThreshold determines how much idle time to wait
    ' for before running the IdleTimeDetected subroutine.
    Private Const conIdleThreshold As Long = 5 * 60& * 1000&
    
    Private PrevControlName As String
    Private PrevFormName As String
    Private ExpiredTime As Long
    
    Private Sub Form_Timer()
        Dim ActiveFormName As String
        Dim ActiveControlName As String
    
        On Error Resume Next
    
        ' Get the active form and control name.
        With Screen
            ActiveFormName = .ActiveForm.Name
            If Err = 2475 Then ActiveFormName = "No Active Form"
            ActiveControlName = .ActiveControl.Name
            If Err = 2474 Then ActiveControlName = "No Active Control"
        End With
    
        ' Record the current active names and reset ExpiredTime if:
        '    1. They have not been recorded yet (code is running
        '       for the first time).
        '    2. The previous names are different from the current ones
        '       (the user has done something different during the timer
        '        interval).
        If (PrevControlName = "") _
        Or (PrevFormName = "") _
        Or (ActiveFormName <> PrevFormName) _
        Or (ActiveControlName <> PrevControlName) Then
            PrevControlName = ActiveControlName
            PrevFormName = ActiveFormName
            ExpiredTime = 0
        Else
            ' ...otherwise the user was idle during the time interval, so
            ' increment the total expired time.
            ExpiredTime = ExpiredTime + Me.TimerInterval
        End If
    
        ' Does the total expired time exceed the conIdleThreshold?
        If ExpiredTime >= conIdleThreshold Then
            ' ...if so, then reset the expired time to zero...
            ExpiredTime = 0
            ' ...Clear the timer event...
            Me.TimerInterval = 0
            ' ...and call the IdleTimeDetected subroutine.
            Call MsgBox("Triggered")
        End If
    End Sub

    Leave a comment:


  • normalice
    replied
    i just pasted your code in with the application.qui t instead of the messagebox. so far it seems to be working just fine.

    Thanks!

    Leave a comment:


  • NeoPa
    replied
    The only thing to come to mind is that you don't clear the timer (Me.TimerInterva l = 0), so the .Quit may fail (as the database has outstanding code running). It's probably a long-shot, but try it out anyway.

    Leave a comment:


  • normalice
    replied
    Code:
    Sub IdleTimeDetected(ExpiredMinutes)
    Application.Quit acQuitSaveNone
    End Sub
    that is the idletimedetecte d subroutine

    It does work as expected when the computer is not locked, and I'll give the beep a shot.

    Leave a comment:


  • NeoPa
    replied
    1. What does the closing code do (Please post it for me)?
    2. Does it work as expected when the PC is not locked?


    In the mean-time, check my version of the code on a test form to see if you come up with the same results as I do.

    Leave a comment:


  • normalice
    replied
    i have it set to close after 7 minutes, but when someone leaves their computer locked with this open all day they come back to find it still open.

    Leave a comment:


  • NeoPa
    replied
    I used a modified version to test with :
    Code:
    Option Compare Database
    Option Explicit
    
    ' conIdleThreshold determines how much idle time to wait
    ' for before running the IdleTimeDetected subroutine.
    Private Const conIdleThreshold As Long = 5 * 60& * 1000&
    
    Private PrevControlName As String
    Private PrevFormName As String
    Private ExpiredTime As Long
    
    Private Sub Form_Timer()
        Dim ActiveFormName As String
        Dim ActiveControlName As String
        Dim lngErr As Long, lngIx As Long
    
        On Error Resume Next
        lngErr = 0
    
        ' Get the active form and control name.
        With Screen
            ActiveFormName = .ActiveForm.Name
            If Err = 2475 Then
                ActiveFormName = "No Active Form"
            ElseIf Err Then
                lngErr = Err
            End If
            ActiveControlName = .ActiveControl.Name
            If Err = 2474 Then
                ActiveControlName = "No Active Control"
            ElseIf Err Then
                lngErr = Err
            End If
        End With
        If lngErr Then
            ' ...Clear the timer event...
            Me.TimerInterval = 0
            Call MsgBox(lngErr)
            For lngErr = 1 To 60
                Beep
                For lngIx = 1 To 100
                    DoEvents
                Next lngIx
            Next lngErr
            Stop
        End If
    
        ' Record the current active names and reset ExpiredTime if:
        '    1. They have not been recorded yet (code is running
        '       for the first time).
        '    2. The previous names are different from the current ones
        '       (the user has done something different during the timer
        '        interval).
        If (PrevControlName = "") _
        Or (PrevFormName = "") _
        Or (ActiveFormName <> PrevFormName) _
        Or (ActiveControlName <> PrevControlName) Then
            PrevControlName = ActiveControlName
            PrevFormName = ActiveFormName
            ExpiredTime = 0
        Else
            ' ...otherwise the user was idle during the time interval, so
            ' increment the total expired time.
            ExpiredTime = ExpiredTime + Me.TimerInterval
        End If
    
        ' Does the total expired time exceed the conIdleThreshold?
        If ExpiredTime >= conIdleThreshold Then
            ' ...if so, then reset the expired time to zero...
            ExpiredTime = 0
            ' ...Clear the timer event...
            Me.TimerInterval = 0
            ' ...and call the IdleTimeDetected subroutine.
            Call MsgBox("Triggered")
            For lngErr = 1 To 60
                Beep
                For lngIx = 1 To 100
                    DoEvents
                Next lngIx
            Next lngErr
            Stop
        End If
    End Sub
    In my testing I found that the code actually did execute. I heard all the beeps then unlocked the screen to find the code at the Stop on line #81.

    What causes you to believe the code isn't executing as intended?

    Leave a comment:


  • normalice
    replied
    The microsoft link in the original question suggests adding this code to a form that you force to open upon the start of Access, and further modify that form's properties to remain hidden so that no one closes it out. This is fine but it can be annoying if you are still trying to fine-tune some components of a database that is already seeing occasional use.

    If you don't mind being less fancy for a spell, disable the code in your startup switchboard such that it does not close out when a new switchboard or form is opened. You might also need to disable the code that attempts to re-open the main switchboard in your secondary switchboard forms. Then, add this code to your main switchboard instead of a hidden form.

    So, if you have work to do and can't risk being interrupted with an untimely close without save, you can just close the main switchboard and not worry about it - well, worry less about it: it is Windows we're talking about...
    Last edited by normalice; Dec 6 '10, 11:01 PM. Reason: further clarification

    Leave a comment:

Working...