Skip to content

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

  1. Recurse into any inner exception first. If ex.InnerException is not Nothing, GetExceptionInfo calls itself recursively on the inner exception and prepends the resulting formatted text to the output before formatting ex itself.
  2. Inspect the exception's runtime type name. GetExceptionInfo compares ex.GetType.Name.ToUpper against the literal "CLSSAIFEXCEPTION".
  3. If the type name matches clsSAIFException: the method reflects over all public properties of the exception's runtime type via System.Reflection.PropertyInfo and appends a "<PropertyName>: <PropertyValue>" line for each one.*
  4. 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.*
  5. Otherwise (any other exception type): the method appends three fixed lines — Message, Source, and Stack Trace (the last spanning multiple lines via ex.StackTrace).
  6. Append a separator. Every call (recursive or not) appends a line of dashes ("-----------------------") after its own formatted block.
  7. 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 InnerException chain produce a proportionally long string; there is no recursion depth limit or cycle guard.*
  • The clsSAIFException type-name check is a literal, case-normalized string comparison ("CLSSAIFEXCEPTION"), not a TypeOf/Is check, 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 standard Message/Source/StackTrace fields.*
  • 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.

Sources

  • Presentation\SAIF.Presentation.ConsoleApplication\clsConsoleBase.vb