diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj
index a899d66..8244912 100644
--- a/TransportPlugin.csproj
+++ b/TransportPlugin.csproj
@@ -339,6 +339,7 @@
+
diff --git a/src/Core/BatchQueueManager.cs b/src/Core/BatchQueueManager.cs
index 7fa8935..002ec97 100644
--- a/src/Core/BatchQueueManager.cs
+++ b/src/Core/BatchQueueManager.cs
@@ -11,6 +11,7 @@ using NavisworksTransport.Core.Collision;
using NavisworksTransport.Core.Config;
using NavisworksTransport.Core.Models;
using NavisworksTransport.Core.Services;
+using NavisworksTransport.Utils;
namespace NavisworksTransport.Core
{
@@ -204,6 +205,9 @@ namespace NavisworksTransport.Core
///
public async Task ProcessQueueAsync()
{
+ // 自动模式:批处理全程窗口自动选择默认动作并立即关闭(排除列表确认/完成汇总/错误提示等)
+ using (AutomationModeContext.EnterAutomaticMode())
+ {
Autodesk.Navisworks.Api.Progress progress = null;
// 统计信息
@@ -406,6 +410,7 @@ namespace NavisworksTransport.Core
TimeSpan duration = endTime - startTime;
ShowBatchSummary(startTime, endTime, duration, totalCount, successCount, failedCount, skippedCount);
}
+ }
}
///
@@ -463,7 +468,14 @@ namespace NavisworksTransport.Core
}
LogManager.Info($"[批处理队列] 执行汇总 - 总计:{totalCount}, 成功:{successCount}, 失败:{failedCount}, 跳过:{skippedCount}, 耗时:{durationText}");
-
+
+ // 自动模式下跳过完成弹窗(汇总已写入日志)
+ if (AutomationModeContext.IsAutomaticMode)
+ {
+ LogManager.Info("[批处理队列] 自动模式下跳过完成汇总弹窗");
+ return;
+ }
+
// 在UI线程显示消息框
System.Windows.Application.Current?.Dispatcher.Invoke(() =>
{
@@ -1043,7 +1055,14 @@ namespace NavisworksTransport.Core
// 排除列表为空,提示用户
LogManager.Warning("[批处理队列] 排除列表为空,需要用户确认");
-
+
+ // 自动模式下跳过确认框,默认继续(不使用排除列表)
+ if (AutomationModeContext.IsAutomaticMode)
+ {
+ LogManager.Info("[批处理队列] 自动模式下跳过排除列表确认,默认继续");
+ return new List();
+ }
+
bool shouldContinue = false;
System.Windows.Application.Current?.Dispatcher.Invoke(() =>
{
diff --git a/src/Core/Collision/ClashDetectiveIntegration.cs b/src/Core/Collision/ClashDetectiveIntegration.cs
index 1df4de3..9935ac0 100644
--- a/src/Core/Collision/ClashDetectiveIntegration.cs
+++ b/src/Core/Collision/ClashDetectiveIntegration.cs
@@ -1305,6 +1305,13 @@ namespace NavisworksTransport
///
private void ShowCancellationMessage()
{
+ // 自动模式下跳过取消提示(日志已记录,避免残留弹窗阻塞自动化)
+ if (AutomationModeContext.IsAutomaticMode)
+ {
+ LogManager.Info("[ClashDetective] 自动模式下跳过检测取消提示框");
+ return;
+ }
+
try
{
// 获取 Navisworks 主窗口句柄作为父窗口
diff --git a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
index 1d7858c..402c448 100644
--- a/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
+++ b/src/UI/WPF/ViewModels/AnimationControlViewModel.cs
@@ -3623,7 +3623,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
{
try
{
- if (DialogHelper.IsTestAutomationModeEnabled)
+ if (AutomationModeContext.IsAutomaticMode)
{
LogManager.Info("[碰撞分析] 自动测试模式下跳过预计算碰撞分析");
SaveCollisionDetectionRecord();
@@ -3861,7 +3861,7 @@ namespace NavisworksTransport.UI.WPF.ViewModels
string routeId = CurrentPathRoute?.Id ?? "";
- if (!DialogHelper.IsTestAutomationModeEnabled)
+ if (!AutomationModeContext.IsAutomaticMode)
{
// 🔥 检查是否已有相同配置的检测记录
var existingRecordResult = CheckExistingDetectionRecord();
@@ -4154,7 +4154,8 @@ namespace NavisworksTransport.UI.WPF.ViewModels
///
private (int id, UserChoice userChoice)? ShowDuplicateConfigDialog(CollisionDetectionRecord record)
{
- if (TestAutomationHttpService.ShouldAutoChooseCreateNewDetectionRecord)
+ if (TestAutomationHttpService.ShouldAutoChooseCreateNewDetectionRecord ||
+ AutomationModeContext.IsAutomaticMode)
{
_lastReusedRecordId = null;
LogManager.Info($"[检测记录] 测试自动化已接管重复配置对话框,自动选择重新生成新记录 (ExistingId={record.Id})");
diff --git a/src/UI/WPF/Views/CollisionAnalysisDialog.xaml.cs b/src/UI/WPF/Views/CollisionAnalysisDialog.xaml.cs
index 2096cba..54b6784 100644
--- a/src/UI/WPF/Views/CollisionAnalysisDialog.xaml.cs
+++ b/src/UI/WPF/Views/CollisionAnalysisDialog.xaml.cs
@@ -67,7 +67,8 @@ namespace NavisworksTransport.UI.WPF.Views
private void CollisionAnalysisDialog_Loaded(object sender, RoutedEventArgs e)
{
- if (!TestAutomationHttpService.ShouldAutoConfirmCollisionAnalysisDialogs)
+ if (!TestAutomationHttpService.ShouldAutoConfirmCollisionAnalysisDialogs &&
+ !AutomationModeContext.IsAutomaticMode)
{
return;
}
diff --git a/src/Utils/AutomationModeContext.cs b/src/Utils/AutomationModeContext.cs
new file mode 100644
index 0000000..e71d81f
--- /dev/null
+++ b/src/Utils/AutomationModeContext.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Threading;
+
+namespace NavisworksTransport.Utils
+{
+ ///
+ /// 自动模式上下文(自动测试 / 批处理执行期间)。
+ ///
+ /// 自动模式下:
+ /// - 窗口(对话框/提示框)自动选择默认动作并立即关闭(或直接跳过弹窗)
+ /// - 保证自动测试与批处理流畅进行,无需人工干预
+ ///
+ /// 进入方式:
+ /// - 批处理执行(BatchQueueManager.ProcessQueueAsync)全程
+ /// - 测试 HTTP 端点(TestAutomationHttpService 计数器,兼容保留)
+ /// - 环境变量 TRANSPORTPLUGIN_TEST_AUTOMATION=1(副实例/测试进程)
+ ///
+ public static class AutomationModeContext
+ {
+ private static int _requestCount;
+
+ ///
+ /// 当前是否处于自动模式(任一来源生效:运行时计数 / 环境变量)。
+ ///
+ public static bool IsAutomaticMode =>
+ Interlocked.CompareExchange(ref _requestCount, 0, 0) > 0 ||
+ DialogHelper.IsTestAutomationModeEnabled;
+
+ ///
+ /// 进入自动模式(可嵌套),Dispose 时退出。
+ ///
+ public static IDisposable EnterAutomaticMode()
+ {
+ Interlocked.Increment(ref _requestCount);
+ return new ActionOnDispose(() =>
+ {
+ if (Interlocked.Decrement(ref _requestCount) < 0)
+ {
+ Interlocked.Exchange(ref _requestCount, 0);
+ }
+ });
+ }
+
+ private sealed class ActionOnDispose : IDisposable
+ {
+ private readonly Action _action;
+
+ public ActionOnDispose(Action action)
+ {
+ _action = action;
+ }
+
+ public void Dispose()
+ {
+ _action?.Invoke();
+ }
+ }
+ }
+}
diff --git a/src/Utils/DialogHelper.cs b/src/Utils/DialogHelper.cs
index ae9044d..b779edc 100644
--- a/src/Utils/DialogHelper.cs
+++ b/src/Utils/DialogHelper.cs
@@ -180,7 +180,7 @@ namespace NavisworksTransport.Utils
MessageBoxImage icon = MessageBoxImage.Information,
int autoCloseMilliseconds = 4000)
{
- if (IsTestAutomationModeEnabled)
+ if (AutomationModeContext.IsAutomaticMode)
{
LogManager.Info($"[DialogHelper] 自动测试模式下跳过自动关闭提示框: {caption}");
return;