Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Graceful Shutdown 1

Status
Not open for further replies.

Scott24x7

Programmer
Jul 12, 2001
2,828
JP
All,
I have tried to create a "shutdown" that will work gracefully whether I'm running my app interactively, or as a compiled .EXE but I seem to be having some "timing" issues with getting everything cleaned up. In my "STARTUP.PRG" I have this code:

Code:
glQUITAPP = .F.
glQUITOPT = 'FOX'
glUSERID = SPACE(10)
glUSERNAME = SPACE(25)
glAXSLEVEL = 0
glMENUOFF = .F.

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
*	Do one time setup for application.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

DO SYSINIT IN COMMON
*
IF WEXIST('PROPERTIES')
	DEACTIVATE WINDOW PROPERTIES
ENDIF
*
ON SHUTDOWN DO CloseApp IN COMMON.PRG
*
SET TALK OFF
*
IF NOT glQUITAPP
	DO MAINMENU.MPR
*	DO MENUINFO
	DO FORM MAIN
	DO FORM SPLASH
	READ EVENTS
ENDIF

Then in my menu for my "Exit" option I have:
Code:
IF WEXIST('MAIN')
	MAIN.DESTROY()
	CLEAR ALL
ELSE
	CLEAR EVENTS
	QUIT
ENDIF

In MAIN.DESTROY() I have:
DO CLOSEAPP IN COMMON.PRG

And That PROC IS:
Code:
PROCEDURE CLOSEAPP

LOCAL lnScreenCount

ON SHUTDOWN
*
SET SYSMENU TO DEFAULT
*
CLOSE ALL
*
CLEAR EVENTS
*
IF NOT USED('STARTUP')
	SELECT 0
	USE DBFS\STARTUP
	IF STARTUP.PRODUCTION
		QUIT
	ELSE
		CANCEL
		CLEAR ALL
	ENDIF
ENDIF

The main problem is, when I exit by either the menu, or the "Close" button on the "MAIN" form, while I'm running in VFP, it does close the app, but the background remains, and if I run the app a 2nd time, I get an immediate "DO CANCLED", and if I run it the 3rd time it runs, repeat steps 1 and 2...

What's a better way to do this???



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
You are making it too difficult.

You will issue a Clear Events from the Quit button on your main form, or menu.

If you are using a main form then in the Form's Destroy event put a Clear Events also.

Then just issue a quit if in the EXE mode or a Return if in Dev Mode.


Don Higgins
 
After your READ EVENTS in your main.prg file you should just tell Fox to exit.

I have a global variable to tell me if this is the development version or the EXE.


For example:
** setup stuff and variables

glexerunning = "EXE" $ UPPER(SYS(16)) && or 'APP' $ UPPER(SYS(16))



Do Form MainForm
Read Events

****************************************************************
*** application quit now process function to leave application properly
****************************************************************
SET SYSMENU TO DEFAULT
SET PROC TO

*-------Close DBF and return environment to default settings
CLEAR WINDOWS
SET BELL ON
SET BELL TO 512,1

***********************************************************************
*** Changed By.: Donald J. Higgins on 20 December 2005
*** Reason.....: Added quick exit if they are in development mode BUT this field has info in it
***********************************************************************
IF glexerunning = .F.
MODIFY WINDOW SCREEN TITLE "Visual FoxPro Dealership Systems Development Mode"
CLOSE DATABASES
CLEAR ALL
RELEASE ALL
Return

ELSE
CLOSE DATABASES
CLEAR ALL
RELEASE ALL
QUIT

ENDIF

******

Don Higgins
 
Crewchief,
I thought once the "Clear Event's" was issued, all processing stopped after that?


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Ok, based on the feedback above, I've done the following, with a few alterations... My intention is to have a single procedure that handles closing of the application regardless of what causes it to exit. So ON SHUTDOWN, MAIN.DESTROY, and my Exit button on my menu all simply issue:

DO CLOSEAPP IN COMMON.PRG

That proc now reads:

Code:
PROCEDURE CLOSEAPP

CLEAR EVENTS
CLEAR ALL
*
ON SHUTDOWN
SET SYSMENU TO DEFAULT
*
IF NOT USED('STARTUP')
	SELECT 0
	USE DBFS\STARTUP
	IF STARTUP.PRODUCTION
		QUIT
	ELSE
		CANCEL
	ENDIF
ENDIF

The "Startup" stuff goes back to my 2.x days, and is how I've always controled the exit status of the application (whether that was to issuea Cancel or a QUIT, depending on what I wanted to happen in the environment).

The problem is, After my CLEAR EVENTS, which I would have thought would "CLEAR" all the Windows, I get the following error message:

Can not clear the object MAIN because it is in use

And it tanks from there... can anyone help me resolve this one?


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Perhaps this does the job:


PROCEDURE CLOSEAPP

CLEAR EVENTS
CLEAR ALL
IF _SCREEN.FORMCOUNT > 0
FOR EACH loForm IN _SCREEN.FORMS
loForm.RELEASE
ENDFOR
ENDIF

*
ON SHUTDOWN
SET SYSMENU TO DEFAULT
*
IF NOT USED('STARTUP')
SELECT 0
USE DBFS\STARTUP
IF STARTUP.PRODUCTION
QUIT
ELSE
CANCEL
ENDIF
ENDIF

 
Rob,
Well, your solution for loForm.RELEASE comes after the CLEAR ALL, which is my offending line, but I liked the idea, and put it before the CLEAR EVENTS, but to no avail, it yielded the same error.


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
And where exactly did you get the same error?
Again at the Clear Events or in the lines I added?

Rob.
 
And again you may try this one:

PROCEDURE CLOSEAPP

IF _SCREEN.FORMCOUNT > 0
FOR EACH loForm IN _SCREEN.FORMS
loForm.Closable = .T.
loForm.Lockscreen = .F.
loForm.ReleaseType = 2
loForm.RELEASE
ENDFOR
ENDIF

CLEAR EVENTS
CLEAR ALL

*
ON SHUTDOWN
SET SYSMENU TO DEFAULT
*
IF NOT USED('STARTUP')
SELECT 0
USE DBFS\STARTUP
IF STARTUP.PRODUCTION
QUIT
ELSE
CANCEL
ENDIF
ENDIF

 
Rob,
In the previous attempts, the error occurs on the CLEAR ALL line, I have watched the trace several times...
I tried your recent code, but I get the error "ReleaseType is read-only", and thus never get to the CLEAR ALL to see if it fixes the problem or not... any other ideas?



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
What if you remove the clear all statement?
If the program exits all is being cleared automatically...

Rob.
 
If I take the "Clear All" out, I am left with a blue background that my MAIN form had as it's background... and if I'm left with that, I must certainly be left with other things... I don't know why I have this. Such a mystery, because the CLEAR EVENTS happens with no problem. Hence, all my hair loss!



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
And if you add:

_screen.backcolor = 16777215
_screen.forecolor = 0
at the place of clear all and issue a release all instead of clear all?

Rob.
 
I think I've got it...

change:
IF WEXIST('MAIN')
MAIN.DESTROY()
CLEAR ALL
ELSE
CLEAR EVENTS
QUIT
ENDIF
to

IF WEXIST('MAIN')
MAIN.RELEASE()
CLEAR ALL
ELSE
CLEAR EVENTS
QUIT
ENDIF

remove what you've got in main.destroy()
I think that should do it.

Rob.
 
None of this seems to work... I don't understand why even if I release the MAIN.RELEASE and then issue the "CLEAR ALL" I continue to get the error "MAIN is in use". If I release it as memory variable with RELEASE MAIN, I can watch both the MAIN Object get released, and then a MAIN value .NULL. get released, and still I get the error. If I let it all execute out, I can see all of my global's still defined in the debug window, and if I then issue a manual CLEAR ALL, it works fine... very annoying.


Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
It's very strange.
I use this kind of shutdown procedure in my programs too.
If an exit is initiated (from within the program or from outside the program) all windows get released and the program shuts down.

You've got a puzzle here...
I'll get back to you when I come up with new ideas on this puzzle...

Rob.
 
Try:

Code:
CLEAR EVENTS
ON SHUTDOWN
IF VARTYPE("Main")="O"
    MAIN.Release()
ENDIF

SET SYSMENU TO DEFAULT

MODIFY WINDOW Screen

RETURN

You don't need either Quit or Cancel because when you run out of code, the program ends.

Tamar

 
Tamar,
You know... that's magic. I realize now that was carry over from my old Fox 2.x days when you had to control where things resolved to, or you program would exit Fox all together, instead of letting you come back to the IDE. Love when the SIMPLER solution prevales. (ala my signature line...)
Sorry it took so long for me to get back to you on this one, have been busy with progressing some of the other areas of my app.



Best Regards,
Scott

"Everything should be made as simple as possible, and no simpler."[hammer]
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top