xsharp.eu • discover runtime error in the RDD classes when running as Windows Service
Page 1 of 2

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 3:50 am
by wriedmann
Hi Robert,
I have now searched a lot until I found my error: an invalid field specification in a DBServer.
My application is running as a Windows service and the runtime error is not showing up (of course!).
If I remember correctly, there is a possibility to make the runtime call an own error handler instead of the X# error dialog.
Unfortunately I cannot find that piece of documentation now.
Thank you very much for any help!
Wolfgang

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 6:41 am
by robert
Wolfgang,
Have you tried registering your error handler with ErrorBlock() ?

Robert

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 6:49 am
by Chris
Hi Wolfgang,

I think it's ErrorBlock() you are looking for?

Edit: Oops, I was too slow :)
.

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 7:03 am
by wriedmann
Hi Robert, hi Chris,
thank you very much!
It was too simple - I was searching for some other call.
I will add that and let you know.
Again: thank you for your great support!
Wolfgang

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 8:20 am
by wriedmann
Hi Robert, hi Chris,
when calling this function from a Core dialect application: how can I create the codeblock?
Wolfgang

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 10:26 am
by Chris
Hi Wolfgang,

Unless Robert has a better idea, I think you'll need to create a small VO dialect library that does this job and it is called by your main core app.

.

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 10:48 am
by robert
Wolfgang, Chris,

To create a codeblock at runtime you should have a look at the compile method of the Workarea class:
https://github.com/X-Sharp/XSharpPublic ... a.prg#L991

Robert

discover runtime error in the RDD classes when running as Windows Service

Posted: Fri Jun 17, 2022 11:16 am
by wriedmann
Hi Robert,
thank you very much! Indeed, that helps.
So I can pass my process class in the codeblock parameter, and call the correct method afterwards.
I'll show my code when it works.
Wolfgang

discover runtime error in the RDD classes when running as Windows Service

Posted: Sat Jun 18, 2022 4:45 pm
by wriedmann
Hi Robert (and all that may be interested),
this is my class to handle these errors:

Code: Select all

using System.Reflection
using XSharp.RDD.Enums
using XSharp.RDD.Support
using XSharp.RDD

public delegate XSErrorHandler( oError as XSharp.Error ) as void

class XSRuntimeHandler
	static protect initonly _oHandler as XSRuntimeHandler
	protect _oError as XSharp.Error
	protect _oErrorHandler as XSErrorHandler

static constructor()

	_oHandler := XSRuntimeHandler{}

	return

protected constructor()

	self:_SetErrorBlock()

	return

protected method _SetErrorBlock() as void
	local oBlock as ICodeblock
	local oMC as IMacroCompiler
	local oType as System.Type
	local lIsBlock as logic
	local lAddsMemvars as logic
	local lIsCodeBlock as logic
	local oBlockType as System.Type
	local cBlock as string
	local oCbType as System.Type

	oBlock := null
	cBlock := "{|o| XSRuntimeHandler.HandleError(o) }"

	try

	oMC := XSharp.RuntimeState.MacroCompiler
	oType := typeof( Workarea )
	if oMC != null
		oBlock  := oMC:Compile( cBlock, true, oType:Module, out lIsBlock, out lAddsMemvars )
		lIsCodeBlock := false
		oBlockType := oBlock:GetType()
		while oBlockType != null
			if oBlockType:FullName != "XSharp._Codeblock"
				oBlockType := oBlockType:BaseType
			else
				lIsCodeBlock := true
				exit
			endif
		enddo
		if ! lIsCodeBlock
			oCbType := null
		    foreach oAsm as Assembly in AppDomain.CurrentDomain:GetAssemblies()
		    	if oAsm:GetName():Name:ToLower() == "xsharp.rt"
		            oCbType := oAsm:GetType( "XSharp._Codeblock" )
		            if oCbType == null
		            	foreach oT as Type in oAsm:GetTypes()
		                    if oT:FullName:ToLower() == "xsharp._codeblock"
		                        oCbType := oT
		                        exit
		                    endif
		                next
		            endif
		        endif
		        if oCbType != null
		            exit
		        endif
		    next
			if oCbType != null
				oBlock  := (ICodeblock) Activator.CreateInstance( oCbType, <object>{ oBlock, cBlock, lIsCodeBlock, lAddsMemvars} )
			endif
		endif
	endif
	ErrorBlock( ( codeblock ) oBlock )

	catch oEx as Exception

	HandleError( XSharp.Error{ oEx } )

	end try

	return

static property Error as XSharp.Error get _oHandler:_oError
static property ErrorHandler as XSErrorHandler set _oHandler:_oErrorHandler := value

static method HandleError( o as XSharp.Error ) as void

	_oHandler:_oError := o
	if _oHandler:_oErrorHandler != null
		_oHandler:_oErrorHandler:Invoke( o )
	endif

	return

end class
and that is how it is used:

Code: Select all

using XSharp.RDD.Enums
using XSharp.RDD.Support
using XSharp.RDD

function Start( ) as void
	local oRDETester			as RDETester

	System.Console.WriteLine("Start test...")
	oRDETester			:= RDETester{}
	if oRDETester:Initialize()
		oRDETester:Process()
	endif
	oRDETester:Dispose()
	System.Console.WriteLine("End test...")
	System.Console.WriteLine("Press return...")
	System.Console.ReadLine()

	return

class RDETester implements IDisposable
protect _oServer as XSharp.VO.SDK.DbServer
protect _cFileName as string

constructor()

	_cFileName := "c:tempRDETester.dbf"

	return

method Initialize() as logic
	local aStruct as array

	XSRuntimeHandler.ErrorHandler := HandleError

	if System.IO.File.Exists( _cFileName )
		System.IO.File.Delete( _cFileName )
	endif

	aStruct := ArrayNew( 2 )
	aStruct[1] := { "F1", "C", 20, 0 }
	aStruct[2] := { "F2", "N", 10, 2 }

	DbCreate( _cFileName, aStruct , "DBFCDX")
	DbCloseArea()

	_oServer := XSharp.VO.SDK.DbServer{ _cFileName, true, false, "DBFCDX" }
	_oServer:Append( true )

	return true

method HandleError( o as XSharp.Error ) as void

	System.Console.WriteLine( "Error has occurred"  )
	System.Console.WriteLine( "Subsystem:" + o:SubSystem )
	System.Console.WriteLine( "Function:" + o:FuncSym )
	System.Console.WriteLine( "Description:" + o:Description )

	return

method Process() as logic

	_oServer:FieldPut( "F1", "hallo" )
	_oServer:FieldPut( "F2", 100 )
	_oServer:FieldPut( "F3", 100 )

	return true

method Dispose() as void

	if _oServer != null
		if _oServer:Used
			_oServer:Close()
		endif
		_oServer			:= null
	endif

	return

end class
The XIDE export file is here:
RDDExceptionTest.zip
(2.85 KiB) Downloaded 62 times
I'm more than sure that many of will find many things to make better.... but this is a proof of concept how things could work.

Wolfgang

discover runtime error in the RDD classes when running as Windows Service

Posted: Mon Jun 20, 2022 7:08 pm
by wriedmann
Hello,
as I expected, there is a lot of space for improvement.
The _SetErrorBlock method can be simplified:

Code: Select all

protected method _SetErrorBlock() as void
	local oBlock as ICodeblock

	oBlock := {|o| XSRuntimeHandler.HandleError( o ) }
	ErrorBlock( ( codeblock ) oBlock )

	return
The code I posted on saturday is only needed if you like to pass in your own errorhandler code.

Wolfgang