diff --git a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs index 2a93f48..154f184 100644 --- a/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs +++ b/src/Drivers/Cli/ZB.MOM.WW.OtOpcUa.Driver.S7.Cli/Commands/ProbeCommand.cs @@ -34,6 +34,10 @@ public sealed class ProbeCommand : S7CommandBase var options = BuildOptions([probeTag]); await using var driver = new S7Driver(options, DriverInstanceId); + // Driver.S7.Cli-003: wrap the entire probe sequence so that a refused/unreachable TCP + // connect still prints the structured Host/CPU/Health lines instead of crashing with a + // full .NET stack trace. InitializeAsync sets health to Faulted with the exception + // message before re-throwing, so GetHealth() always has something to report. try { await driver.InitializeAsync("{}", ct); @@ -48,6 +52,20 @@ public sealed class ProbeCommand : S7CommandBase await console.Output.WriteLineAsync(); await console.Output.WriteLineAsync(SnapshotFormatter.Format(Address, snapshot[0])); } + catch (OperationCanceledException) + { + throw; // Ctrl+C — let CliFx handle it normally. + } + catch + { + // Connect / read failure — print what the driver knows so far. + var health = driver.GetHealth(); + await console.Output.WriteLineAsync($"Host: {Host}:{Port}"); + await console.Output.WriteLineAsync($"CPU: {CpuType} rack={Rack} slot={Slot}"); + await console.Output.WriteLineAsync($"Health: {health.State}"); + if (health.LastError is { } err) + await console.Output.WriteLineAsync($"Last error: {err}"); + } finally { await driver.ShutdownAsync(CancellationToken.None);