A refused unix socket raises SocketException, which derives from
Win32Exception rather than IOException, so it escaped the filter meant to
skip one unreachable process and failed the whole concurrent enumeration
instead: a machine where any .NET process exits between the port scan and
the connect showed an empty list. The classification is now a named
predicate covering both transports.
Two dialog defects shared a shape - state left behind by a query nobody is
waiting for any more. Rebuilding the bound collection on every filter
keystroke made the grid drop its selection and write that null back,
discarding the assemblies of a process the new filter still matched; and the
branch taken when nothing is selected cleared no loading flag, while the
query it superseded was no longer allowed to, so the progress bar animated
over an empty pane. Relatedly, the two-second command budget expired into a
process listed with null metadata, which made a slow machine look like a
runtime that answered with nothing; it is longer now, and expiry names the
process it gave up on, since the only thing that ever reaches the far end of
that budget is a runtime which will never answer.
The test gaps are closed the same way: a real dynamic assembly pins the
in-memory classification, the managed-only assertion is stated as the
property instead of a list of native names to exclude, and the .NET
Framework path gets live tests. Those showed that a desktop CLR process
mostly reports NGen native images rather than the IL assemblies behind them,
which is now recorded as the fidelity gap it is.
Assisted-by: Claude:claude-opus-5:Claude Code