fix: dispatch controlled AutoCAD exit from idle
This commit is contained in:
@@ -128,6 +128,7 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
|
||||
private int? before, after1, after2, afterUndo;
|
||||
private AutomationEntityCounts? baseline, counts1, counts2, countsUndo;
|
||||
private readonly List<string> transitions = ["Created"];
|
||||
private bool exitQueued;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
@@ -164,8 +165,7 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
|
||||
{
|
||||
transitions.Add("LifecycleProbeCompleted");
|
||||
WriteEvidence(true, null);
|
||||
transitions.Add("ExitRequested");
|
||||
AcadApplication.Quit();
|
||||
RequestControlledExit();
|
||||
}
|
||||
|
||||
private void OnIdle(object? sender, EventArgs e)
|
||||
@@ -256,12 +256,40 @@ internal sealed class FirstLimitedApplyAutomationCoordinator
|
||||
AcadApplication.DocumentManager.DocumentActivated -= OnDocumentActivated;
|
||||
WriteEvidence(success, error);
|
||||
if (document is not null) document.CloseAndDiscard();
|
||||
AcadApplication.Quit();
|
||||
RequestControlledExit();
|
||||
}
|
||||
catch { }
|
||||
finally { selectedTargetSnapshotId = null; pxpResults.Clear(); }
|
||||
}
|
||||
|
||||
// AutoCAD's direct Application.Quit can leave a startup-script host alive.
|
||||
// Dispatching the native QUIT command from the next quiescent Idle cycle
|
||||
// preserves normal command shutdown semantics.
|
||||
private void RequestControlledExit()
|
||||
{
|
||||
if (exitQueued) return;
|
||||
exitQueued = true;
|
||||
transitions.Add("ExitQueued");
|
||||
AcadApplication.Idle += OnExitIdle;
|
||||
}
|
||||
|
||||
private void OnExitIdle(object? sender, EventArgs args)
|
||||
{
|
||||
AcadApplication.Idle -= OnExitIdle;
|
||||
try
|
||||
{
|
||||
var active = AcadApplication.DocumentManager.MdiActiveDocument;
|
||||
if (active is null) { AcadApplication.Quit(); return; }
|
||||
transitions.Add("NativeQuitDispatched");
|
||||
active.SendStringToExecute("_.QUIT _N ", true, false, false);
|
||||
}
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
RuntimeDiagnostics.Write("AutomationControlledExitFailed", "ERROR", resultStatus: "AUTOMATION_CONTROLLED_EXIT_FAILED", exception: exception);
|
||||
AcadApplication.Quit();
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteEvidence(bool success, string? error)
|
||||
{
|
||||
if (config is null) return;
|
||||
|
||||
@@ -82,6 +82,14 @@ public sealed class FoundationTests
|
||||
Assert.Contains("PostStartupReady", source);
|
||||
}
|
||||
|
||||
[Fact] public void AutomationControlledExit_UsesNativeQuitFromIdle()
|
||||
{
|
||||
var source = File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "FirstLimitedApplyAutomation.cs"));
|
||||
Assert.Contains("RequestControlledExit", source);
|
||||
Assert.Contains("AcadApplication.Idle += OnExitIdle", source);
|
||||
Assert.Contains("active.SendStringToExecute(\"_.QUIT _N \", true, false, false)", source);
|
||||
}
|
||||
|
||||
[Fact] public void PrimaryCommand_IsRegistered() => Assert.Contains("[CommandMethod(\"PHP_REC_ANNOT\")]", File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "EntryPoint.cs")));
|
||||
[Fact] public void LegacyAliases_AreRegistered() => Assert.True(File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "EntryPoint.cs")).Contains("PXP-AAV") && File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "EntryPoint.cs")).Contains("PXP-OA"));
|
||||
[Fact] public void RibbonCommand_ReferencesRegisteredCommand() => Assert.Contains("PHP_REC_ANNOT ", File.ReadAllText(Path.Combine(ProjectRoot, "src", "PRecAnnot.Plant3D2026", "EntryPoint.cs")));
|
||||
|
||||
Reference in New Issue
Block a user