Mastering ExceptionFinder for Reflector — A Practical GuideReflector is a powerful .NET decompiler and assembly browser used by developers to inspect compiled code, understand libraries, and diagnose issues. ExceptionFinder is an add-on/tool designed to surface exceptions that are thrown within assemblies—especially useful when source code is unavailable or when trying to trace unexpected runtime behavior. This guide walks through what ExceptionFinder does, why it matters, how to install and configure it, workflows for common debugging scenarios, advanced techniques, and best practices to get the most from the tool.
What is ExceptionFinder?
ExceptionFinder is a static-analysis tool integrated with Reflector (or used alongside it) that scans compiled assemblies for locations where exceptions are constructed, thrown, or caught. Instead of relying on runtime tracing alone, ExceptionFinder inspects IL (Intermediate Language) and decompiled C#/VB code to identify exception-related patterns: throw instructions, calls to exception constructors, and exception handling blocks (try/catch/finally). The result is a map of potential exception sources across an assembly, which speeds up debugging, auditing, and security reviews.
Why it matters
- Pinpointing exception sources in third-party or legacy assemblies where source code is unavailable.
- Understanding how a library reports and wraps errors, which helps when writing correct exception handling in client code.
- Auditing for swallowing exceptions or broad catches that obscure root causes.
- Identifying places to add logging, retries, or compensating actions in your own codebase.
Installing and configuring ExceptionFinder
-
Obtain the tool:
- If ExceptionFinder is an official Reflector add-in, download it from the vendor’s add-ins repository or the developer’s website.
- If it’s a third-party utility, ensure you download from a trusted source and verify signatures or checksums where available.
-
Install into Reflector:
- Open Reflector and go to the Add-Ins or Extensions menu.
- Choose “Install Add-In” (or follow vendor instructions) and select the ExceptionFinder package.
- Restart Reflector if prompted.
-
Configure scanning options:
- Scope: choose whether to scan a single assembly, a group of assemblies, or entire folders.
- Granularity: set whether you want IL-level scanning only, decompiled C#/VB inspection, or both.
- Filters: exclude certain namespaces, assemblies, or patterns (e.g., generated code, third-party frameworks).
- Output: choose formats for results — in-GUI reports, exportable CSV/JSON, or annotated assemblies.
-
Permissions and safety:
- ExceptionFinder performs static analysis only; it does not execute code. Still run it in a controlled environment if handling untrusted binaries.
- Respect licensing and intellectual property when analyzing third-party assemblies.
Basic usage and interpreting results
Typical workflow:
- Load assemblies you want to inspect into Reflector.
- Launch ExceptionFinder from the Add-Ins menu or toolbar.
- Select the scan scope and start the scan.
- Review results organized by assembly, type, and method.
Common result fields:
- Location: assembly → namespace → type → method.
- Exception type(s): the specific exception classes constructed or thrown (e.g., System.InvalidOperationException).
- Instruction(s): IL instruction(s) where throw or newobj occur.
- Catch blocks: methods that catch and rethrow or swallow exceptions.
- Severity/notes: heuristics indicating likely importance (e.g., uncaught exceptions, broad catch of System.Exception).
Interpreting items:
- A method with a throw instruction indicates it explicitly raises an exception. Check message strings and constructor arguments to understand context.
- A new exception object followed by a throw usually indicates the code is wrapping or translating errors — follow call chains to find the original cause.
- Catch blocks that log and rethrow preserve stack traces when using throw; when using throw ex (in C#), they reset the stack trace — look for that pattern.
- Empty catch blocks or catches that only return default values indicate swallowed exceptions and potential silent failures.
Practical debugging scenarios
-
Finding where a runtime exception originates
- If your application raises an exception but stack traces are limited (e.g., due to obfuscation or catching), scan the relevant assemblies for throw/newobj instructions for the exception type. Prioritize methods that construct the same message or pass inner exceptions.
-
Diagnosing wrapped exceptions
- ExceptionFinder can show where code creates new exceptions passing other exceptions as inner exceptions. Follow these to locate the original throw point.
-
Locating swallowed exceptions
- Search for catch blocks with no logging, empty bodies, or broad catches that return default values. These are prime suspects when functionality silently fails.
-
Auditing third-party libraries
- Scan dependencies for broad catches of System.Exception, use of exception filters, and rethrow patterns that can hinder observability. Export results to CSV for team review.
-
Preparing for robust error handling
- Use ExceptionFinder to identify where to add logging, add custom exception types, or implement retries. Focus on methods that are public API entry points or that deal with I/O and external systems.
Advanced techniques
- Decompilation-assisted triage: Enable decompiled code analysis to get method source alongside IL instructions. This helps when message strings or arguments are used in conditional logic determining exception creation.
- Pattern searches: Create rules to find specific anti-patterns like throw inside finally, catch { } with no body, or instantiation of certain exception types (e.g., NotImplementedException).
- Combining with call-graph analysis: Use Reflector’s call tree features to trace callers of methods that throw exceptions; prioritize top-level entry points used by your application.
- Prioritization heuristics: Assign weights for results based on public visibility, frequency of use, and whether exceptions cross assembly boundaries.
- Automated reporting: Configure ExceptionFinder to emit JSON/CSV reports and integrate these into CI pipelines for continuous auditing of exceptions introduced by new builds.
Best practices when using ExceptionFinder
- Focus scans: Limit to assemblies relevant to your application to avoid noise from system or framework assemblies.
- Validate findings: Static analysis can give false positives (e.g., exception types referenced but not thrown at runtime); confirm suspicious locations by runtime testing or additional inspection.
- Watch for obfuscation: Some obfuscators can hide exception creation patterns; combine ExceptionFinder with runtime diagnostics when possible.
- Use consistent exception policies: When you find repeated patterns (e.g., broad catches), standardize handling across the codebase—log, wrap with meaningful context, preserve stack traces, and avoid swallowing.
- Keep results private: Treat third-party or internal assemblies’ internals as sensitive when sharing reports.
Limitations
- Static-only: ExceptionFinder analyzes code statically and may miss dynamically constructed exceptions or ones thrown via reflection/dynamic methods at runtime.
- False positives/negatives: Some IL patterns may be misattributed without context; runtime behavior can differ.
- Dependent on decompiler accuracy: If Reflector’s decompilation has errors, the analysis may be harder to interpret.
- Not a replacement for logging and telemetry: Use it to augment runtime diagnostics, not replace them.
Example: quick walkthrough
- Load MyApp.Core.dll and MyApp.Utils.dll in Reflector.
- Run ExceptionFinder on both assemblies with decompiled output enabled and exclude System.* namespaces.
- Results show:
- MyApp.Core.Service.Process -> throws System.InvalidOperationException with message “Invalid state”.
- MyApp.Utils.IOHelper.Read -> catches Exception and returns null (swallows).
- Actionable steps:
- For Process: add validation earlier or handle InvalidOperationException where Process is called.
- For Read: modify catch to log and rethrow a more specific exception, or return Result
/Option pattern instead of null.
Conclusion
ExceptionFinder for Reflector is a targeted, practical tool to reveal where exceptions are created, thrown, or swallowed inside compiled assemblies. It accelerates debugging when source code is missing, helps audit third-party libraries, and supports improving error-handling practices. Use it alongside runtime telemetry and a consistent exception policy for the most reliable results.
Leave a Reply