Specially GUI applications can show a undesiderable behavior if the encounter a failure before the GUI is initialized. That can be a missing and needed DLL, a runtime error in the initialization of the GUI itself or some other undesired behavior. The solution is to implement an own startip method that uses alternative ways to display the error and exit, maybe using the Windows Console and/or writing to an error log. The implementation differs a bit depending if you have a migrated VO application or a natively written .NET application mainly because of the different handling of namespaces. For the handling of namespace in migrated applications please see here: /ins Compiler option This is a sample code for an own startup class in a migrated application:
using System.Runtime.InteropServices class XStartupCode [STAThreadAttribute]; static method Start() as void strict local oSB as System.Text.StringBuilder try StartupExceptionTester.Exe.Functions.Start() catch oEx as Exception AllocConsole() oSB := System.Text.StringBuilder{} Output( oSB, "An unhandled exception has occurred" ) Output( oSB, "===================================" ) do while oEx != null Output( oSB, "Exception: " + oEx:Message ) Output( oSB, "Callstack:") Output( oSB, oEx:StackTrace ) Output( oSB, "" ) oEx := oEx:InnerException enddo Output( oSB, "===================================" ) Output( oSB, "Press Return to close the application" ) Console.ReadLine() MessageBox( 0, oSB:ToString(), "Runtime error", 0 ) System.IO.File.AppendAllText( System.IO.Path.Combine( AppDomain.CurrentDomain:BaseDirectory, "ApplicationError.log" ), oSB:ToString() ) end try return static method Output( oSB as System.Text.StringBuilder, cText as string ) as void oSB:AppendLine( cText ) Console.WriteLine( cText ) return [DllImport("kernel32.dll", SetLastError := true)]; [return: MarshalAs(UnmanagedType.Bool)]; static extern method AllocConsole() as logic [DllImport("user32.dll", CharSet := CharSet.Ansi)]; static method MessageBox(hwnd as IntPtr, lpText as string, lpCaption as string, uType as dword) as int pascal end class
To define this class as startup class, you have to add a compiler option:
-main:XStartupCode
Please see here for a sample as XIDE application export file: startupexceptiontester.zip
For a native .NET application with namespaces the code changes a bit:
class ProdPlan.XStartupCode [STAThreadAttribute]; static method Start as void local oSB as System.Text.StringBuilder
where ProdPlan
is the namespace of your application.
The compiler option than has to be
-main:ProdPlan.XStartupCode
To explain: since the GUI can be not yet started when an exception is occurring, the console mode needs to be activated so the error can be shown even with no GUI (and written to a file for later evaluation).