test: add controlled Plant 3D 2026 runtime smoke mode
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using Autodesk.AutoCAD.ApplicationServices;
|
||||
using Autodesk.AutoCAD.EditorInput;
|
||||
using Autodesk.AutoCAD.Runtime;
|
||||
@@ -9,9 +10,19 @@ namespace PRecAnnot.Plant3D2026;
|
||||
|
||||
public sealed class EntryPoint : IExtensionApplication
|
||||
{
|
||||
public void Initialize() => RibbonIntegration.Register();
|
||||
public void Initialize()
|
||||
{
|
||||
RuntimeDiagnostics.Write("AssemblyInitializeStarted");
|
||||
RibbonIntegration.Register();
|
||||
RuntimeDiagnostics.Write("AssemblyInitializeCompleted");
|
||||
}
|
||||
|
||||
public void Terminate() { }
|
||||
public void Terminate()
|
||||
{
|
||||
RuntimeDiagnostics.Write("AssemblyTerminateStarted");
|
||||
RibbonIntegration.Terminate();
|
||||
RuntimeDiagnostics.Write("AssemblyTerminateCompleted");
|
||||
}
|
||||
|
||||
[CommandMethod("PHP_REC_ANNOT")]
|
||||
public void PrimaryCommand() => RunDiagnostic("PHP_REC_ANNOT");
|
||||
@@ -24,57 +35,148 @@ public sealed class EntryPoint : IExtensionApplication
|
||||
|
||||
private static void RunDiagnostic(string commandName)
|
||||
{
|
||||
var operationId = Guid.NewGuid().ToString("N");
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
Document? document = null;
|
||||
RuntimeDiagnostics.Write("CommandStarted", operationId: operationId, commandName: commandName);
|
||||
|
||||
try
|
||||
{
|
||||
Document? document = AcadApplication.DocumentManager.MdiActiveDocument;
|
||||
if (document is null)
|
||||
return;
|
||||
|
||||
Editor editor = document.Editor;
|
||||
if (PlantApplication.CurrentProject is null)
|
||||
document = AcadApplication.DocumentManager.MdiActiveDocument;
|
||||
var project = PlantApplication.CurrentProject;
|
||||
var details = new Dictionary<string, object?>
|
||||
{
|
||||
editor.WriteMessage("\nP_Rec_Annot: активный Plant 3D project не найден; DWG не изменён.");
|
||||
["IsPlantProjectOpen"] = project is not null,
|
||||
["IsOrthoDrawing"] = false,
|
||||
["ViewportCount"] = null,
|
||||
["DataLinksAvailable"] = DataLinksAvailable(project)
|
||||
};
|
||||
|
||||
if (document is null || project is null)
|
||||
{
|
||||
RuntimeDiagnostics.Write("CommandPreflightCompleted", operationId: operationId, commandName: commandName, resultStatus: "PreflightRejected", document: document, details: details);
|
||||
WriteEditor(document, "\nP_Rec_Annot: Активный Plant 3D-проект не найден; DWG не изменён.");
|
||||
WriteUsage(operationId, commandName, "PreflightRejected", document, details, stopwatch.ElapsedMilliseconds);
|
||||
RuntimeDiagnostics.Write("CommandCompleted", operationId: operationId, commandName: commandName, resultStatus: "PreflightRejected", document: document, details: details);
|
||||
return;
|
||||
}
|
||||
|
||||
editor.WriteMessage($"\nP_Rec_Annot {commandName}: Plant 3D project '{PlantApplication.CurrentProject.Name}' найден; diagnostic-only, DWG не изменён.");
|
||||
RuntimeDiagnostics.Write("CommandPreflightCompleted", operationId: operationId, commandName: commandName, resultStatus: "PreflightAccepted", document: document, details: details);
|
||||
if (SmokeGuard.IsSmoke) SmokeGuard.EnsureReadOnly();
|
||||
WriteEditor(document, $"\nP_Rec_Annot {commandName}: Plant 3D-проект '{project.Name}' найден; Smoke/diagnostic-only, DWG не изменён.");
|
||||
WriteUsage(operationId, commandName, "PreflightAccepted", document, details, stopwatch.ElapsedMilliseconds);
|
||||
RuntimeDiagnostics.Write("CommandCompleted", operationId: operationId, commandName: commandName, resultStatus: "PreflightAccepted", document: document, details: details);
|
||||
}
|
||||
catch (SmokeWriteBlockedException exception)
|
||||
{
|
||||
RuntimeDiagnostics.Write("CommandFailed", "ERROR", operationId, commandName, "SMOKE_WRITE_BLOCKED", exception, document);
|
||||
WriteUsage(operationId, commandName, "SMOKE_WRITE_BLOCKED", document, null, stopwatch.ElapsedMilliseconds, exception);
|
||||
WriteEditor(document, "\nP_Rec_Annot: SMOKE_WRITE_BLOCKED; запись запрещена.");
|
||||
}
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
try { AcadApplication.DocumentManager.MdiActiveDocument?.Editor.WriteMessage($"\nP_Rec_Annot: безопасная диагностика завершилась ошибкой: {exception.Message}"); }
|
||||
catch { }
|
||||
RuntimeDiagnostics.Write("CommandFailed", "ERROR", operationId, commandName, "Failed", exception, document);
|
||||
WriteUsage(operationId, commandName, "Failed", document, null, stopwatch.ElapsedMilliseconds, exception);
|
||||
WriteEditor(document, $"\nP_Rec_Annot: безопасная диагностика завершилась ошибкой: {exception.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private static bool DataLinksAvailable(Autodesk.ProcessPower.ProjectManager.PlantProject? project)
|
||||
{
|
||||
try { return PlantApplication.ProjectPart("Piping")?.DataLinksManager is not null; }
|
||||
catch { return false; }
|
||||
}
|
||||
|
||||
private static void WriteUsage(string operationId, string commandName, string resultStatus, Document? document, IReadOnlyDictionary<string, object?>? details, long duration, System.Exception? exception = null)
|
||||
{
|
||||
var eventDetails = new Dictionary<string, object?>
|
||||
{
|
||||
["ObjectsExamined"] = 0,
|
||||
["AnnotationsCreated"] = 0,
|
||||
["AnnotationsUpdated"] = 0,
|
||||
["AnnotationsDeleted"] = 0,
|
||||
["AnnotationsSkipped"] = 0,
|
||||
["WarningCount"] = 0,
|
||||
["ErrorCount"] = exception is null ? 0 : 1,
|
||||
["DurationMilliseconds"] = duration
|
||||
};
|
||||
if (details is not null) foreach (var item in details) eventDetails[item.Key] = item.Value;
|
||||
RuntimeDiagnostics.Write("CommandUsageEvent", exception is null ? "INFO" : "ERROR", operationId, commandName, resultStatus, exception, document, eventDetails);
|
||||
}
|
||||
|
||||
private static void WriteEditor(Document? document, string message)
|
||||
{
|
||||
try { document?.Editor.WriteMessage(message); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
internal static class RibbonIntegration
|
||||
{
|
||||
private const string TabId = "PRecAnnot.Plant3D2026";
|
||||
private const string PanelId = "PRecAnnot.Plant3D2026.Annotations";
|
||||
private const string ButtonId = "PRecAnnot.Plant3D2026.PHP_REC_ANNOT";
|
||||
private const string Command = "PHP_REC_ANNOT ";
|
||||
private static bool deferred;
|
||||
|
||||
public static void Register()
|
||||
{
|
||||
RuntimeDiagnostics.Write("RibbonInitializationStarted");
|
||||
try
|
||||
{
|
||||
RibbonControl? ribbon = ComponentManager.Ribbon;
|
||||
if (ribbon is null) return;
|
||||
|
||||
RibbonTab? tab = ribbon.Tabs.FirstOrDefault(item => string.Equals(item.Id, TabId, StringComparison.OrdinalIgnoreCase));
|
||||
if (tab is null)
|
||||
if (ComponentManager.Ribbon is null)
|
||||
{
|
||||
tab = new RibbonTab { Id = TabId, Title = "Промхимпроект" };
|
||||
ribbon.Tabs.Add(tab);
|
||||
if (!deferred)
|
||||
{
|
||||
ComponentManager.ItemInitialized += OnItemInitialized;
|
||||
deferred = true;
|
||||
}
|
||||
RuntimeDiagnostics.Write("RibbonInitializationCompleted", resultStatus: "Deferred");
|
||||
return;
|
||||
}
|
||||
|
||||
if (tab.Panels.Any(panel => string.Equals(panel.Source?.Title, "Аннотации", StringComparison.OrdinalIgnoreCase))) return;
|
||||
|
||||
RibbonPanelSource source = new() { Title = "Аннотации" };
|
||||
source.Items.Add(new RibbonButton { Text = "Аннотировать", ShowText = true, CommandParameter = Command });
|
||||
tab.Panels.Add(new RibbonPanel { Source = source });
|
||||
RegisterNow();
|
||||
}
|
||||
catch
|
||||
catch (System.Exception exception)
|
||||
{
|
||||
// Ribbon is optional; command-line registration remains available.
|
||||
RuntimeDiagnostics.Write("RibbonInitializationCompleted", "ERROR", exception: exception, resultStatus: "Failed");
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnItemInitialized(object? sender, System.EventArgs args)
|
||||
{
|
||||
if (ComponentManager.Ribbon is null) return;
|
||||
ComponentManager.ItemInitialized -= OnItemInitialized;
|
||||
deferred = false;
|
||||
Register();
|
||||
}
|
||||
|
||||
private static void RegisterNow()
|
||||
{
|
||||
RibbonControl ribbon = ComponentManager.Ribbon!;
|
||||
RibbonTab? tab = ribbon.Tabs.FirstOrDefault(item => string.Equals(item.Id, TabId, StringComparison.OrdinalIgnoreCase));
|
||||
if (tab is null)
|
||||
{
|
||||
tab = new RibbonTab { Id = TabId, Title = "Промхимпроект" };
|
||||
ribbon.Tabs.Add(tab);
|
||||
}
|
||||
|
||||
RibbonPanel? panel = tab.Panels.FirstOrDefault(item => string.Equals(item.Source?.Id, PanelId, StringComparison.OrdinalIgnoreCase));
|
||||
if (panel is not null)
|
||||
{
|
||||
RuntimeDiagnostics.Write("RibbonAlreadyExists", resultStatus: "AlreadyExists");
|
||||
RuntimeDiagnostics.Write("RibbonInitializationCompleted", resultStatus: "AlreadyExists");
|
||||
return;
|
||||
}
|
||||
|
||||
RibbonPanelSource source = new() { Id = PanelId, Title = "Аннотации" };
|
||||
source.Items.Add(new RibbonButton { Id = ButtonId, Text = "Аннотировать", ShowText = true, CommandParameter = Command });
|
||||
tab.Panels.Add(new RibbonPanel { Source = source });
|
||||
RuntimeDiagnostics.Write("RibbonInitializationCompleted", resultStatus: "Created");
|
||||
}
|
||||
|
||||
public static void Terminate()
|
||||
{
|
||||
if (!deferred) return;
|
||||
ComponentManager.ItemInitialized -= OnItemInitialized;
|
||||
deferred = false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user