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!

Error Handling 2

Status
Not open for further replies.

David Higgs

Programmer
May 6, 2012
392
GB
Further to discussions on another thread: -
I thought it would be beneficial to start a new thread.

As a recreational Developer / User of VFP, any applications I may write are for my own personal use. My main Hobbies are Amateur Radio and British Railways (1948 to 1968) I use VFP / MySQL to support them.

One area of VFP I have been very lax in is that of Error Handling. Often I come across an error and then find a fix for it, which I know is know is wrong, prevention is better than a cure. As I am the end user, I am keen to put the code to good use.

I am improving, albeit at a slow pace.

One area of Error Handling (amongst several others) is that I would like to learn about using AERROR(laError).

In the other thread:-
Mike Lewis said:
it would be worth familiarising yourself with the various ways of using ON ERROR and TRY / CATCH / FINALLY (and possibly the Error method in objects, although that is something that I have never used, rightly or wrongly).

Thank you Mike, I will take a look at the above commands.


Regards,

David.

Recreational user of VFP.
 
David,

AERROR() is most useful for errors reported by SQLEXEC() or from a COM component. You can use it with native VFP errors as well, but in that case it doesn't give you much useful information that you won't get with a call to ON ERROR. Put another way, you don't use AERROR() to detect an error, but rather to give you information about an error detected by other means.

I understand your point about being your own end user. As we discussed elsewhere, when working in the development environment, is often better not to build error-handling into your program but instead to rely on VFP's native error handler, which is essentially the familiar Cancel / Suspend / Ignore dialogue.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thank you Mike,

I generally run my applications from the IDE and when I come across an Error, I invariably end up terminating the program using Task Manager; if I could avoid that, it would be a blessing. I do compile and also use MyApp.EXE this normally exits on error by closing down.

Regards,

David.

Recreational user of VFP.
 
I generally use code like this

Code:
PROCEDURE USUAL
	PARAMETERS MLINENO,MPROG
	PRIVATE MPROG,MLINENO,MSGLINE
	PRIVATE m.ERRORNO
	PRIVATE m.MSGSTRING
	PRIVATE m.SERIOUS
	PRIVATE OHTTP
	m.SERIOUS = .T.
	m.ERRORNO = ERROR()
	m.MSGSTRING = MESSAGE()
	MSGLINE = ""
	DO CASE
		CASE m.ERRORNO = 1426 .AND. "0x80070003"$m.MSGSTRING
			MSGLINE = m.SYSTEMNAME + " is unable to load and control Microsoft Word using OLE"+m.CRLF+m.CRLF+;
				"THERE ARE A NUMBER OF POSSIBLE REASONS FOR THIS:"+m.CRLF+m.CRLF+;
				"A) YOU MAY NOT HAVE WORD INSTALLED AT ALL."+m.CRLF+;
				"B) THE OLE AUTOMATION COMMAND FOR WORD MAY BE SET INCORRECTLY."+m.CRLF+m.CRLF+;
				"PLEASE CHECK THAT WORD IS INSTALLED AND/OR TRY SETTING THE LOCATION FOR WORD MANUALLY "+m.CRLF+;
				"(AVAILABLE FROM THE 'OTHER UTILITIES' MENU - 'IMPORT/EXPORT BACK-UP AND RESTORE TAB')."+m.CRLF+m.CRLF+;
				"IF NONE OF THE ABOVE WORK, CONTACT YOUR IT SUPPORT"
		CASE UPPER(m.MSGSTRING) = "ERROR LOADING PRINTER" .OR. UPPER(m.MSGSTRING) = "ERROR ACCESSING PRINTER"
			MSGLINE = m.SYSTEMNAME + " is unable to print"+m.CRLF+;
				"THERE ARE A NUMBER OF POSSIBLE REASONS FOR THIS:"+m.CRLF+m.CRLF+;
				"A) THE PRINTER MAY NOT BE CONNECTED, OR MAY BE OUT OF PAPER."+m.CRLF+;
				"B) THE DRIVER MAY BE CORRUPTED, ON LOCATED ON ANOTHER MACHINE."+m.CRLF+;
				"C) YOU MAY HAVE A DEFAULT PRINTER SET FOR "+m.SYSTEMNAME+" which conflicts with your current selection."+m.CRLF+m.CRLF+;
				"PLEASE CHECK OR TRY ANOTHER PRINTER - OR RESET YOUR "+m.SYSTEMNAME+" default and try again."+m.CRLF+m.CRLF+;
				"IF NONE OF THE ABOVE WORK, CONTACT YOUR IT SUPPORT"
		OTHERWISE
			MSGLINE = "Sorry! An Error Has Occurred: "+CHR(13)+CHR(10)
			MSGLINE = MSGLINE + "Error No.: "+ALLTRIM(STR(m.ERRORNO))+CHR(13)+CHR(10)
			MSGLINE = MSGLINE + "Nature: "+m.MSGSTRING+CHR(13)+CHR(10)
			MSGLINE = MSGLINE + "Details:"+MESSAGE(1)+CHR(13)+CHR(10)
			IF PARAMETERS() >1
				MSGLINE = MSGLINE + "Procedure:"+MPROG+CHR(13)+CHR(10)
			ENDIF
			IF PARAMETERS() >0
				MSGLINE = MSGLINE + "Line No.:"+ALLTRIM(STR(MLINENO))+CHR(13)+CHR(10)
			ENDIF
			MSGLINE = MSGLINE + CHR(13)+CHR(10)
			MSGLINE = MSGLINE + "It would be very helpful if you wrote down the "+CHR(13)+CHR(10)
			MSGLINE = MSGLINE + "details above when calling for assistance."+CHR(13)+CHR(10)

			*QUIT
	ENDCASE
	IF m.SERIOUS
		MESSAGEBOX(MSGLINE,48,"Error")
		ON SHUTDOWN
		CANCEL
	ENDIF
	RETURN

You set this one up with a call like this in your code
Code:
ON ERROR DO USUAL WITH LINENO(),PROGRAM()

I have other error handlers - one specially for file related errors - which is essentially a do nothing error handler.
Code:
PROCEDURE FILEERR
	RETURN

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.
 
I invariably end up terminating the program using Task Manager

Hmmm. I can't imagine why you would need to do that. In most cases, an error would eventually trigger a Cancel / Suspend / Ignore dialogue, which gives you an immediate exit. The program might appear to hang as a result of an endless loop, but you can usually deal with that by setting ESCAPE on.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike Lewis said:
The program might appear to hang as a result of an endless loop, but you can usually deal with that by setting ESCAPE on.

I have SET ESCAPE OFF with a note about Suppressing MySQL Connection Messages. No idea!

Any way I've set it to on now.

Regards,

David.

Recreational user of VFP.
 
Let me just sketching the idea of a readevents method you return to by RETURN TO MASTER.
In this example involving a loop repeatedly reinitializing the app.

Code:
goApp = NewObject("myapp")
Do While goApp.lContinue
   goApp.initialize()
   goApp.readevents()
EndDo 
goApp = .null.

Procedure errorhandling()
   Lparameters lcProgram, lnLine
   =AError(laError)
   ? "Error:", laError[1,1], laError[1,2], "in line", lnLine, " of ", lcProgram
   * to quit in some cases set goApp.lContonue =.f.
   Return To Master
   
Define Class myapp as Custom
   lContinue = .t.
   
   Procedure Init()
      On Error Do errorhandling with Program(), Lineno()
      On Shutdown Quit
   EndProc  
   
   Procedure initialize()
      Close Tables All
      Clear Dlls
      Release All Except goApp
      * exit with ALT+F4
      On Key Label ALT+F4 clear events

      * use functions with F1, F2
      On Key Label F1 goApp.functionality1()
      On Key Label F2 goApp.functionality2()
   EndProc 
   
   Procedure functionality1()
      ? Datetime()
   EndProc
   
   Procedure functionality2()
      ExecScript("dskjdjskljkl")
   EndProc

   Procedure readevents()
      Read Events
      This.lContinue = .f.
   EndProc
   
   Procedure Destroy()
      Activate Screen
      Clear
      Messagebox("Bye!")
   EndProc
EndDefine
There is one good reason to keep a general error handler just a procedure in main.prg:
No matter what happens and even if you CLEAR ALL the main.prg will only vanish from the callstack when you exit, it's also what RETURN TO MASTER returns to. So actually even the stack level 1, the method readevents is removed and you get back to after the readevents call. But only a CLEAR EVENTS causes the line after read events to execute.

Bye, Olaf.

Olaf Doschke Software Engineering
 
And to add to what Mike Lewis alreay told about AERROR(), even for one type of native VFP error it gives extra information: When a database trigger fails.
The AERROR help topic tells you more about the composition of the array generated.

What also is interesting especially when you run in the IDE is ASTACKINGO(). You get the technical information the callstack window in the debugger is about. Now instead of clicking into the callstaack and get to the calling code in the trace window you get the names of programs/(methods of objects in the array and see the path code went before arriving where you are now.

Unlike AERROR() only making sense after an error happened, ASTACKINGO() can give you that information all the time in all your code. It becomes less when you build without debug information. Within the IDE no problem, another good reason to run your own code within the IDE.

AERROR() run at any time can give you information about any error that happened last, so also don't call it after every SQLExec() or other SQL passthrough functions just because they potentially set error information there and don't actually trigger an error. That is true, but you get a negative return value from SQLExec and that is your sogn to call AERROR() for details.

Bye, Olaf.

Olaf Doschke Software Engineering
 
Olaf said:
Let me just sketching the idea of a readevents method you return to by RETURN TO MASTER.

Thank you for the demo program, a quick test with F1 revealed DATE / Time F2 the Syntax error and the Bye! when I quit. I will see how I can make use of this code within my applications.

Regards,

David.

Recreational user of VFP.
 
Olaf said:
What also is interesting especially when you run in the IDE is ASTACKINGO(). You get the technical information the callstack window in the debugger is about. Now instead of clicking into the callstack and get to the calling code in the trace window you get the names of programs/(methods of objects in the array and see the path code went before arriving where you are now.

I know all of the VFP Commands are in the Help File, I've never looked at ASTACKINGO(). I can see that it would be quite useful for a Developer / User.

I will try and improve on improving the Error Handling with all of the advice being offered. Sometimes getting the application to do what is required takes priority over Error Handling. I must try to break this circle.

Regards,

David.

Recreational user of VFP.
 
By the way, I only used the F keys as posting a menu.mpr would be far too much. That or a toolbar, a mainform... Whatever your usual user interface is, can of course also be started. F1 was just a working functionality and F2 one that errors. Not much of an example about a destabilized IDE. But going through goApp.initialize() after the error handler did not set goApp.lContinue to .F. means you can get the application back to a well-defined state there.

Obviously that won't make it faster than a restart as you go through initialize in application start, too, but you could decide that once ON ERROR is set that's never a setting that becomes forgotten and that DLL DECLARES won't need to be redone unless the error actually is about a DLL. You could also do things usually not necessary at application start like close all forms, revert all transactions etc., but in the end you can keep the IDE or even the application going as long as all such initialization and tidy up routines work.

Bye, Olaf.

Olaf Doschke Software Engineering
 
David,

Just to pick up on one earlier point. You mentioned "a note about Suppressing MySQL Connection Messages".

I think this refers to the DispWarnings setting in the connection properties. If set .T., VFP will display an error message if a back-end database (such as MySQL) returns an error. This would be appropriate in your case, as it would let you see the error and try to resolve it straight away.

In a normal run-time environment, you would set DispWarnings to .F. and you would check the return value from functions such as SQLCONNECT() and SQLEXEC() to detect an error. You would then call AERROR() to get more information about the error (such as the actual message returned by the back end).

You can set DispWarnings from Tools > Options > Remote Date, or by calling SQLSETPROP().

Mike




__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Mike Lewis said:
Just to pick up on one earlier point. You mentioned "a note about Suppressing MySQL Connection Messages".

I think this refers to the DispWarnings setting in the connection properties. If set .T., VFP will display an error message if a back-end database (such as MySQL) returns an error. This would be appropriate in your case, as it would let you see the error and try to resolve it straight away.

I probably changed the state of SET ESCAPE during or after my transferring my Databases from DBF to MySQL.

I've changed to SET ESCAPE ON now and will read through all of the help received with a view of improving the ERROR HANDLING.

I should have asked for more help along the way, then I could have added Error Handling as I progressed. Most of the errors I suffer though are during Development so I fix them as I go along. The main issues I have is not being able to exit the program after an error and also the dreaded "File in use" when trying to open the relevant PRG File.





Regards,

David.

Recreational user of VFP.
 
Olaf said:
By the way, I only used the F keys as posting a menu.mpr would be far too much. That or a toolbar, a mainform... Whatever your usual user interface is, can of course also be started.

Yes, I very much appreciated your code and will look at using it as a basis for my Error Handling.

Most of my Programming, Z80 Assembler, Arduino, dBASE and VFP started by using / modifying example software. So I study your and others example code (in various threads) to glean ideas.




Regards,

David.

Recreational user of VFP.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top