Debugger Replacement (OpenInsight 32-Bit)
At 29 MAR 2010 01:50:43AM Barry Stevens wrote:
Does anyone have an example of a DEBUGGER REPLACEMENT ssp, that they have working in a live environment.
At 29 MAR 2010 10:54AM Richard Hunt wrote:
Barry,
Basically the following program I created records the error information that caused the debugger call. It records the error information in a Revelation table and an operating system (Windows) file.
There are references to FUNCTIONS that I created and they are used for collecting more information about the user status.
FUNCTION DEBUGGER_REPLACEMENT(ARG1)
* Program: DEBUGGER_REPLACEMENT
* Module: PROCEEDURE
* Copyright 2000, Richard S. Hunt, All Rights Reserved.
* Audit trail. * Mod.0 07/08/07 Standard Debugger replacement. * Mod.9 08/10/09 Add AUTOLOGOUT and INACTIVITY. * Mod.9 08/10/09 Add CLOSE_ACCOUNT option (ARG1 field 3 in DISPLAY_MESSAGE subroutine. *
* Declare statements.
DECLARE FUNCTION DISPLAY_MESSAGE, NEXT_AVAIL, SYSLOGINS_SUB, SYSMSG*
* Set program variables. $INSERT VARS $INSERT RTI_DEBUG_COMMON WINDOW=@WINDOW PATH=DRIVE():'\TEMP\OIDebug.txt' *
* Open files.
OPEN 'ERRORS' TO ERRORS_DATA ELSEERRORS_DATA=NOTHING$ENDOSOPEN PATH TO OS_DATA ELSEOSWRITE NOTHING$ TO PATHOSOPEN PATH TO OS_DATA ELSEOS_DATA=NOTHING$ENDEND*
* Get user information. USER_NUMBER=NOTHING$ FIELD_NAMES=LEVEL':FM$:'NAME':FM$:'AUTOLOGOUT':FM$:'INACTIVITY' FIELD_VALUES=NOTHING$ SUCCESS=SYSLOGINS_SUB('READ',FIELD_NAMES,USER_NUMBER,FIELD_VALUES,ERROR) USER_LEVEL=FIELD_VALUES USER_NAME=FIELD_VALUES AUTOLOGOUT=FIELD_VALUES INACTIVITY=FIELD_VALUES *
* Enhance error message.
ERROR=NOTHING$ERROR=FIELD(SPSTATCODE@,CHAR(0),2)ERROR=FIELD(SPSTATCODE@,CHAR(0),3)ERROR=FIELD(SPSTATCODE@,CHAR(0),4)ERROR_MESSAGE=SYSMSG(ERROR)*
* Check for null error message. IF ERROR_MESSAGE EQ NOTHING$ THEN RETURN END *
* Display error message for user.
MESSAGE=ERROR_MESSAGEMESSAGE := TM$:TM$:'Notify your Sys Admin that this error has occured.'MESSAGE := TM$:TM$:'This is a fatal error.'MESSAGE := TM$:'You will be logged out when you close this window.'RESULT=DISPLAY_MESSAGE('ERROR':FM$:TRUE$:FM$:TRUE$,MESSAGE,NOTHING$,'H')*
* Enhance call stack. CALL_STACK=CALLSTACK@ CONVERT FM$:VM$ TO VM$:SM$ IN CALL_STACK *
* Accumulate error data.
ERRORS_RECORD=NOTHING$ERRORS_RECORD=DATE()ERRORS_RECORD=TIME()ERRORS_RECORD=@DBIDERRORS_RECORD=@USERNAMEERRORS_RECORD=@STATIONERRORS_RECORD=@USER0ERRORS_RECORD=USER_NAMEERRORS_RECORD=@STATIONERRORS_RECORD=USER_LEVELERRORS_RECORD=ERROR_MESSAGEERRORS_RECORD=SPSTATUS@ERRORS_RECORD=CALLDEPTH@ERRORS_RECORD=LINENO@ERRORS_RECORD=CALL_STACKERRORS_RECORD=AUTOLOGOUTERRORS_RECORD=INACTIVITYERRORS_RECORD=WINDOW*
* Write error data to file. IF ERRORS_DATA NE NOTHING$ THEN ERRORS_ID=NEXT_AVAIL('ERRORS',NOTHING$,'ERRORS*NEXT') WRITE ERRORS_RECORD TO ERRORS_DATA, ERRORS_ID ELSE END END *
* Write error data to OS file.
IF OS_DATA NE NOTHING$ THENOSREAD OS_RECORD FROM OS_DATA ELSEOS_RECORD=NOTHING$ENDSWAP CHAR(13):CHAR(10):STR('_',30):CHAR(13):CHAR(10) WITH FM$ IN OS_RECORDOS_RECORD=FIELD(OS_RECORD,FM$,1,99)ERRORS_RECORD=Date=:OCONV(ERRORS_RECORD,'D4/')ERRORS_RECORD=Time=:OCONV(ERRORS_RECORD,'MTHS')ERRORS_RECORD=Database=:ERRORS_RECORDERRORS_RECORD=LoginERRORS_RECORD=Station=:ERRORS_RECORDERRORS_RECORD=UserERRORS_RECORD=UserERRORS_RECORD=User nbr=:ERRORS_RECORDERRORS_RECORD=User level=:ERRORS_RECORDERRORS_RECORD=Error message=:ERRORS_RECORDERRORS_RECORD=SP status=:ERRORS_RECORDERRORS_RECORD=Call depth=:ERRORS_RECORDERRORS_RECORD=Line number=:ERRORS_RECORDERRORS_RECORD=Call stack=:ERRORS_RECORDERRORS_RECORD=Autologout=:ERRORS_RECORDERRORS_RECORD=Inactivity=:ERRORS_RECORDERRORS_RECORD=Window=:ERRORS_RECORDERRORS_RECORD=Error number=:INSERT(ERRORS_RECORD,1,0,0,ERRORS_ID)SWAP FM$ WITH CHAR(13):CHAR(10) IN ERRORS_RECORDOS_RECORD=INSERT(OS_RECORD,1,0,0,ERRORS_RECORD)SWAP FM$ WITH CHAR(13):CHAR(10):STR('_',30):CHAR(13):CHAR(10) IN OS_RECORDOSWRITE OS_RECORD TO OS_DATAOSCLOSE OS_DATAENDRETURN
At 29 MAR 2010 08:11PM Barry Stevens wrote:
Thanks, that looks great, just one questions, how does DISPLAY_MESSAGE display the message to the user.
At 29 MAR 2010 08:38PM Barry Stevens wrote:
'SYSMSG' , is that a revelation utility from somewhere or one of yours.
If code is available I would welcome it.
tia
-Barry
At 30 MAR 2010 05:15AM Richard Hunt wrote:
Barry,
It is one of mine. Not much to it. Here it is…
SUBROUTINE SYSMSG(ARG1)
* Program: SYSMSG
* Module: PROCEEDURE
* Copyright 2000, Richard S. Hunt, All Rights Reserved.
* Audit trail. * Mod.0 01/28/07 Structure a system error message. *
* Declare statements.
*
* Set program variables. $INSERT VARS RESULT=NOTHING$ STATUS_CODES=ARG1 CONVERT ',' TO VM$ IN STATUS_CODES OS_FILE=DRIVE():'\REVERROR.DAT' *
* Verify status codes.
IF STATUS_CODES EQ NOTHING$ THENRESULT=NOTHING$RETURN RESULTEND*
* Read REVERROR.DAT record. OSREAD STRINGS FROM OS_FILE ELSE RESULT=NOTHING$ RETURN RESULT END SWAP CHAR(13):CHAR(10) WITH FM$ IN STRINGS *
* Get next status code.
LAST_FIELD=COUNT(STATUS_CODES,FM$) + (STATUS_CODES NE NOTHING$)FOR FIELD=1 TO LAST_FIELDSTRING=STATUS_CODESERROR_CODE=OCONV(STRING,'UDC_UPPER')ERROR_ARGS=DELETE(STRING,1,1,0)*
* Find error line. ERROR_TEXT=NOTHING$ POS=FALSE$ MORE=(STRINGS NE NOTHING$) LOOP WHILE MORE REMOVE STRING FROM STRINGS AT POS SETTING MORE CODE=TRIM(FIELD(STRING,':',1)) IF CODE EQ ERROR_CODE THEN ERROR_TEXT=TRIMF(FIELD(STRING,':',2,99999)) MORE=FALSE$ END REPEAT *
* Format error text.
IF ERROR_ARGS NE NOTHING$ THENLAST_VALUE=COUNT(ERROR_ARGS,VM$) + (ERROR_ARGS NE NOTHING$)FOR VALUE=1 TO LAST_VALUESWAP '%':VALUE:'%' WITH ERROR_ARGS IN ERROR_TEXTNEXT VALUEENDRESULT=ERROR_TEXTNEXT FIELD*
**
* Return result.
RETURN RESULT
At 30 MAR 2010 05:39AM Richard Hunt wrote:
Barry,
DISPLAY_MESSAGE is something I created. It does things that is unique to my software. I suggest you replace it with the MSG function.
If you are wondering about closing the application, I use the following sentence…
RESULT=UTILITY('DESTROY','SYSTEM')I figure if the debugger is called then I want the application to close. That way the user must restart the application.
At 30 MAR 2010 06:55AM Barry Stevens wrote:
]]I suggest you replace it with the MSG function
Appears the MSG function wont work, so, I was wodering how you displayed your message to the user.
At 30 MAR 2010 07:34AM Barry Stevens wrote:
Thanks very much.
At 30 MAR 2010 07:34AM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
Barry,
When you're in debugger_replacement you're essentially in an error condition - the idea is that you handle the error doing as little as possible within Basic+ and then let the engine return to being idle, or as Richard does, exit the system.
The Msg() procedure is quite complex and involved - if you wanted to display a message to the user we'd recommend using the Windows API MessageBox function as most of the processing will take place outside of OI. We also tend to simply log the error to a table or update the Windows event log…
World leaders in all things RevSoft
At 30 MAR 2010 02:52PM Richard Hunt wrote:
Barry,
Hope this helps.
Basically all my windows (forms) have an EDIT LINE control, that is what the FORM DESIGNER calls it. This EDIT LINE is anchored at the bottom and auto sizes the width. It is used for displaying copyright information and any messages I want the user to see. I find this method to be less intrusive to the user rather than having a window pop up.
My DISPLAY_MESSAGE simply verifies that this EDIT LINE control exists and then uses the SET_PROPERTY function to display the messages in this EDIT LINE control. It also does a MESSAGEBEEP, colors the message accordingly, allows for timed messages and allows me to have "user type" customization.
By default, basic users get a simple message displayed. More advanced users get a more detailed error message displayed. And system administrators get the complete error message displayed.
At 30 MAR 2010 06:02PM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
This approach can be useful if all you are trying to trap is errors in your own programs but if you're in the debugger because you've lost the network connection or there's a GFE in SYSOBJ then the system won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the….
World leaders in all things RevSoft
At 30 MAR 2010 06:03PM [url=http://www.sprezzatura.com]The Sprezzatura Group[/url] wrote:
This approach can be useful if all you are trying to trap is errors in your own programs but if you're in the debugger because you've lost the network connection or there's a GFE in SYSOBJ then the system won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the debugger to report an error in reading which will invoke the replacement debugger which won't be able to read these ancillary programs so no updates will be able to happen, rather they'll call the….
World leaders in all things RevSoft
At 30 MAR 2010 07:47PM Barry Stevens wrote:
OK, thanks.
I would have expected a better *working* DEBUGGER_REPLACEMENT example in OI (uses msg to display).