INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Best practices on closing vfp app on inactivity

Best practices on closing vfp app on inactivity

(OP)
First, Let me say it has taken 10 years to get back to where I could post on this forum. Before then I was a regular poster (more questions that help). Not sure if anyone is still here that used to post regularly and that helped me over the years but if they are I want to first say Thank You. For 30+ years now I have an app that I developed and maintain. At some point many years ago I made an attempt to shutdown my app when users stay logged in for hours and days. I really need to reindex and things like that overnight. I do have users legitimately in the system 24/7. I am revisiting this issue. My question has to do with an overall concept. I have decided in order to close my app on inactivity, it really has to be context sensitive, in other words, it depends what the user is doing. For example, a user may be adding a record in one of the data entry screens. If that is the case, I would need to release the views/cursors, etc that are in use at that time and THEN quit the app. At the same time, that makes doing the shutdown a lot more complex because my app has over 100 tables and 1200 views. I am asking if I am making this too complex? All thoughts appreciated.

RE: Best practices on closing vfp app on inactivity

First, welcome back. I don't remember you as regular, though I am also here since 2004.

CODE

QUIT 

It can be as simple as that, as that doesn't do, what people think it does and quit right away. Quit causes the destroy of any object, which means every object can tidy up itself and its resources. In regard of forms, Quit causes QueryUnload. within that method you can find out from THISFORM.ReleaseType, that the unload is queries by Foxpro shutting down. Which either means a system shutdown or a QUIT happened. In both cases you can have a specific auotmatic reaction differing from a normal interactive or programmatic release of a form.

Because of the nature of system shutdowns to enforce processes quitting, even though that may never happen automatically in your case, it is best practice to program defensive and have automatic rollbacks. Think alone about automatic restarts after automatic windows updates.

In one or two aspects VFP has some automatic behavior anyway. In regard of remote data there is the DisconnectRollback setting of SQLSETPROP to specify, what happens with ongoing transactions when disconnecting. Likewise closing a table as a to be destroyed datasession must do, will normally revert buffered changes. I'm not 100% sure, but if the VFP team had decided for autoupdate/commit intead of autrever/trollback, they would risk FoxPro sessions to get into conflicts and thus failing to end the datasession.

Filehandles are released on their own and databases and any involved files are closed anyway, with or without your intervention. And this happens thoroughly and stable, unless the reason for the runtime shutown is a fatal error (C5), which is not the case with a QUIT.

Also, QUIT does trigger what you define via ON SHUTDOWN, and as already stated while explaining the ReleaseType property of forms, that also is triggered by a system shutdown.

Simply make a few experiments especially about what happens to buffered changes.

There are reasons to "manually" let your code close single tables and in case errors are triggered log them, as such things would happen unnoticed when you jus rely on automatic tidying up of the VFP runtime. But it doesn't pay to have a general shutdown code acting on all currently open forms and memory variables. It is good practice to QUIT to let each object and form act on its own behalf and then only be concerned about some very general things like ASSESSIONS telling you about any data sessions, TXNLEVEL telling about any uncommitted transactions etc. One of the pains is message boxes without a timeout. As they are not VFP forms, they do not have a QueryUnload happening, of course. Same goes for the legacy native report preview AFAIK. So there are a few bummers to take care for, but very broadly you still can use QUIT because of the ON SHUTDOWN procedure you can define, that is your resort for such things. I have to lie about it, but I think whatever you define to happen ON SHUTDOWN will happen after all single forms and object should already be terminated. It's easy enough to test. If I am right, any remaining forms then indicate something has dangling references or similar nasty bugs.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

Another topic is how to decide about inactivity. As I understand your question, this is not your major topic, you have ideas about that. A typical solution is an inactivity timer resetting whenever there is something you call activity. Not limited to keyboard and mouse events.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

2
Hi and welcome back. I'm sorry I don't remember you, but then I often don't remember people I met last week.

You say that you need the solution to be context-sensitive. If a user is in the middle of an edit, you need to recognise that fact. You can't simply kill their instance of the application, because that would cause them to lose data.

In that case, what you really need is to broadcast some sort of warning. Tell all logged-in users that you are going to close the system in so-many minutes, and they had better log out before then or else (of course, you will choose suitably diplomatic language).

To make that happen, each instance of the app would have a timer that fires every, say, 60 seconds. The timer checks for the presence of some sort of "signal". The signal could be a flag within a table, or it could be the presence of a certain file in a given directory. The point is that you (the administrator) creates the signal. The individual timers check to see if it exists. If it does, the warning message is displayed on the user's screen. At that point, another timer is set, with an interval equal to the length of the warning period. When that timer fires, you shut down the user's instance.

At the point of shutting down, you can't simply issue a QUIT. You have to worry about those unsaved edits, etc. Also, when you issue a QUIT, VFP will systematically close each of the open forms, firing all the code in the various Destroy, QueryUnload, etc. methods. Any of that code could interfere with the shutdown process. For example, it might simply ask the user if he is sure he wants to quit, in which case he might well answer no.

To deal with that, what you need to do is to first revert all unsaved buffers and rollback all incomplete transactions. Then issue these commands:

CODE -->

DECLARE Integer ExitProcess IN WIN32API 
ExitProcess() 

That will kill the application stone dead - no arguments.

Of course, there are many other issues. What do you do about a user who is performing some critical operation which cannot be interrupted? What happens if the administrator changes his mind? - you need a mechanism for cancelling the shutdown warning. What if a user logs in after you have issued the warning but before you have shut down? Or if a user tries to log in after you have shut down but before you have completed the task that requires exclusive access? Those issues all have to be dealt with, but none of them affects the overall concept.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: Best practices on closing vfp app on inactivity

OK, so now you have two opposing recommendations.

Mike argues QUIT is unfortunate, as any code could hinder the shutdown. I argue you have to program for the case and don't hinder but support the shutdown with your code. ExitProcess is a fallback to me, that should only be done as a last resort solution.

The situation of a user in an edit is not something complicated, as that simply means your QueryUnload code will depend on ReleaseType and in the normal case ask the user, whether to cancel changes or stay, while a shutdown will cause code to automatically rollback/revert and let the shutdown proceed.

The idea to warn users is a good one, so they can cooperate, but the main issue is users leaving open an application after the end of work. In these cases, such warnings go unread anyway. But it wouldn't matter, if they also just are having a timeout, this just means a delay of the shutdown. You can't do so in case Windows decides to shutdown, after an update, though you can roughly define windows update behaviour.

I would still go for QUIT and just ensure no code you do interferes with an automatic shutdown and causes any questions and dialogs when form.ReleaseType is 2.

A compromise is to start a timer doing an EXITPROCESS after a longer interval. Then QUIT and give the normal unloading and destroy mechanisms and code a chance to quit before the timer event calls the ExitProcess to enforce it.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

(OP)
Olaf and Mike, I can see good advice in both your posts and I thank you for both.

I do believe both your posts tend to make me believe that Yes, it does depend on what the user is doing, at least to some extent. I've decided to greatly limit use of this shutting down process. It will only take place in a couple of forms that are specifically used by non administrative personnel (my least literate users) to perform a specific task during "non business hours". That will make accomplishing this a lot easier. I am going to do some testing with the Quit command. I was using KEYBOARD'(ALT+F4)'. I want to see if QUIT does some of the work for me with regard to shutting down these particular forms gracefully.

I do have a lot of messagebox's and until now I have not used the timeout setting. I am going to look into how I might make use of that as well. These are mostly modal forms and the aforementioned keyboard shortcut will not work on modal forms and on messageboxes. I will post my findings.

Thanks again,
John

RE: Best practices on closing vfp app on inactivity

Yes, we've had this discussion about KillProcess before. I agree that you should give the user the opportunity to cleanly close down first. KillProcess mainly covers the case where the user had gone home and left the application running, or for some reason simply refuses to close the application properly.

By all means take steps to ensure that your code won't interfere with a QUIT-triggered shutdown. But it's complicated. Just one issue that comes to mind is if a modal form is active when QUIT is executed. That would normally give rise to a "Cannot quit Visual FoxPro" message. True, you could program round that. But there are probably several such cases, and the relevant code could be quite far-reaching.

We haven't touched on the issue of detecting a period of inactivity. I've never found a satisfactory way of doing that. That's why I favour the idea of broadcasting a warning message. But that's just one approach that can be taken.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads

RE: Best practices on closing vfp app on inactivity

Modal forms are a showstopper, too. At least normal modal forms also get the QueryUnload event triggered and if you don't do anything to block the unload the modal forms do unload.

Adding a timeout to messageboxes also only is half a solution. You then still hope the shutdown is not triggered when a messagebox is currently displayed, you hope any last messagebox a user left open and went away is already gone by timeout, when you do the QUIT by some external signal. That also makes a pre shutdown phase useful, in which you first only announce to want to shutdown in say 5 minutes. Such additional messagex could come from a timer starting an alert form when the timer event finds a shutdown signal like a boolean value in a table or a file existing.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

Mike, I think it's just a matter of discipline to have QueryUnload code in your base form and specialize it in case you need to in derived classes. Same goes for any other class destroy.

Also simply have ON SHUTDOWN QUIT and also modal forms will not cause the "Foxpro Cannot Quit" message. Indeed whatever you define as ON SHUTDOWN action has priority over this native behaviour and I now think after experimenting happens before any form and objects are unloaded, released, and destroyed.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

Here a demonstration about QUIT with modal forms:

CODE

ON KEY LABEL F4 goForm.Release()
ON KEY LABEL F5 QUIT
ON SHUTDOWN QUIT

PUBLIC goForm
goForm = CREATEOBJECT("modform")
goForm.Show(1)

DEFINE CLASS modform as Form
   WindowType =  1
   
   PROCEDURE QueryUnload()
      DO Case
         CASE thisform.ReleaseType = 1
            MESSAGEBOX("you tried interactive closing (you clicked close [X]) Not allowed")
            NODEFAULT
         CASE thisform.ReleaseType = 2
            This.Closable = .T.
            MESSAGEBOX("shutdown (you pressed F5)")
      ENDCASE
   ENDPROC
   
   PROCEDURE Release()
       MESSAGEBOX("form release (you pressed F4), ReleaseType is "+TRANSFORM(thisform.ReleaseType))
   ENDPROC 
ENDDEFINE 

Notice 1: ReleaseType 0 does not cause a QueryUnload, so form.Release() circumvents QueryUnload. You could call QueryUnload from the Release method to have one place of reacting to form closing requests and add the CASE ThisForm.ReleaseType = 0.

Notice 2: This demos, that you can also reject the closing via NODEFAULT. You can of course also prevent closing by setting form.Closable = .F., so the [X] close button in the title bar is disabled.
That also is the reason I set Closable = .T. to not have anything in the way of quitting the form.

Notice 3: If you comment out ON SHUTDOWN you get the "Foxpro cannot quit" message Mike warns about. So defining what happens ON SHUTDOWN is solving that.

Notice 4: pressing F5 causes QUIT, which in turn causes the ON SHUTDOWN definition to come into effect. So doing QUIT is causing the same events within the VFP session as quitting VFP by closing the _SCREEN and also the same events, a computer shutdown triggers in VFP. Though this is not two-way, i.e. a QUIT does not shut down the PC, of course. It only shuts down the VFP session.

Now you can add more cleanup code as you like in each case. The behavior surely should differ in case of a click of [X] to show warning messages for unsaved changes, while you want to automatically revert them in the case of ReleaseType 2.

In case you want to react with more cleanup code in ON SHUTDOWN notice I found out this happens first, see via this sample usage:

CODE

ON KEY LABEL F4 goForm.Release()
ON KEY LABEL F5 QUIT
ON SHUTDOWN myQUIT()

PUBLIC goForm
goForm = CREATEOBJECT("modform")
goForm.Show(1)

DEFINE CLASS modform as Form
   WindowType =  1
   
   PROCEDURE QueryUnload()
      DO Case
         CASE thisform.ReleaseType = 1
            MESSAGEBOX("you tried interactive closing (you clicked close [X]) Not allowed")
            NODEFAULT
         CASE thisform.ReleaseType = 2
            This.Closable = .T.
            MESSAGEBOX("shutdown (you pressed F5)")
      ENDCASE
   ENDPROC
   
   PROCEDURE Release()
       MESSAGEBOX("form release (you pressed F4), ReleaseType is "+TRANSFORM(thisform.ReleaseType))
   ENDPROC 
ENDDEFINE

PROCEDURE myQUIT()
    MESSAGEBOX("myQuit was triggered")
    QUIT
ENDPROC 

Press F5 and the "myQuit was triggered" message is displayed first, then the message from the form QueryUnload. Also, try out to shut down your computer as a final test.

I don't just recommend ending your own myQUIT procedure with the QUIT command. The shutdown procedure stops and the application does not QUIT if you don't call QUIT again. That also means doing QUIT in the routine initially triggered by QUIT or by any other shutdown event trigger is, fortunately, not recursive, so doing QUIT inside myQUIT won't trigger myQUIT again and cause an endless loop. That's also why ON SHUTDOWN QUIT in the simplest case works and does not cause endless calls of QUIT itself. It's worth mentioning in that detail level, as QUIT really triggers ON SHUTDOWN and still can be used as the reaction to the shutdown in the simplest case, to make it circumvent VFPs native "Cannot Quit" message.

Last, not least: The ON KEY definition, of course, is not, what you use in your application, but a timer eventually doing a QUIT, when it detects a reason/signal to quit and after it alerted about the upcoming shutdown.

Bye, Olaf.

RE: Best practices on closing vfp app on inactivity

One further idea:

If only some forms hinder you to administratively open tables exclusive, you will not need to trigger the whole application shutdown by a QUIT but only release certain forms. For that use case a form handler is good, in which you (by definition of the form handler meaning) define a method to start forms and keep form references and related metadata like form class and type and also define a method to close certain form types based on that metadata you maintain about running forms.┬┤QueryUnload and he ReleaseType still comes in handy in these cases, too, to differentiate between normal users closing forms interactively and your shutdown timer acting programmatically.

Bye, Olaf.

Red Flag This Post

Please let us know here why this post is inappropriate. Reasons such as off-topic, duplicates, flames, illegal, vulgar, or students posting their homework.

Red Flag Submitted

Thank you for helping keep Tek-Tips Forums free from inappropriate posts.
The Tek-Tips staff will check this out and take appropriate action.

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close