Exception diagnostics formatting¶
Downstream applications call GetExceptionInfo from a Catch block to turn an exception (and its full inner-exception chain) into one formatted, human-readable string suitable for console output or a log file, without each application re-implementing exception reflection logic.
| Field | Value |
|---|---|
| Operation ID | OP-CA-003 |
| Trigger | Downstream error-handling code catches an Exception and calls GetExceptionInfo(ex) |
| Inputs | ex As Exception |
| Outputs | Formatted diagnostic String |
| Primary components | clsConsoleBase.GetExceptionInfo |
| Entry point | Presentation\SAIF.Presentation.ConsoleApplication\clsConsoleBase.vb |
Steps¶
- Recurse into any inner exception first. If
ex.InnerExceptionis notNothing,GetExceptionInfocalls itself recursively on the inner exception and prepends the resulting formatted text to the output before formattingexitself. - Inspect the exception's runtime type name.
GetExceptionInfocomparesex.GetType.Name.ToUpperagainst the literal"CLSSAIFEXCEPTION". - If the type name matches
clsSAIFException: the method reflects over all public properties of the exception's runtime type viaSystem.Reflection.PropertyInfoand appends a"<PropertyName>: <PropertyValue>"line for each one.* - This means any public property exposed by the framework's custom exception type (not imported or declared in this library) is surfaced automatically, without this library needing to know its shape in advance.*
- Otherwise (any other exception type): the method appends three fixed lines —
Message,Source, andStack Trace(the last spanning multiple lines viaex.StackTrace). - Append a separator. Every call (recursive or not) appends a line of dashes (
"-----------------------") after its own formatted block. - Return the accumulated string, which is inner-exception text (if any) followed by the current exception's formatted block and separator.
Process flow¶
The following diagram visualizes the recursive inner-exception walk.
flowchart TD
Start([GetExceptionInfo called with ex]) --> HasInner{ex.InnerException<br>is not Nothing?}
HasInner -->|Yes| Recurse[Recursively format<br>inner exception first]
HasInner -->|No| CheckType
Recurse --> CheckType{Type name is<br>CLSSAIFEXCEPTION?}
CheckType -->|Yes| ReflectProps[Reflect public properties<br>and format each as Name: Value]
CheckType -->|No| StdFields[Format Message, Source,<br>Stack Trace]
ReflectProps --> Separator[Append dashed separator]
StdFields --> Separator
Separator --> Return([Return accumulated string])
Failure and edge-case behavior¶
- Exceptions with a deep
InnerExceptionchain produce a proportionally long string; there is no recursion depth limit or cycle guard.* - The
clsSAIFExceptiontype-name check is a literal, case-normalized string comparison ("CLSSAIFEXCEPTION"), not aTypeOf/Ischeck, so any exception type whose runtime type name happens to match that literal — regardless of namespace or assembly — is treated as the SAIF custom exception and reflected instead of using the standardMessage/Source/StackTracefields.* - Reflection over the custom exception's public properties will throw if a property getter itself throws; this is not caught within
GetExceptionInfo.*
Note: Statements marked with
*were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.
Related documentation¶
Sources¶
Presentation\SAIF.Presentation.ConsoleApplication\clsConsoleBase.vb