[CmdletBinding()] param( [Parameter(Position = 0)] [string]$ModelPath ) $ErrorActionPreference = 'Stop' $scriptDirectory = Split-Path -Parent $MyInvocation.MyCommand.Path $repoRoot = Split-Path -Parent $scriptDirectory $defaultsFilePath = Join-Path $scriptDirectory 'test-automation.defaults.json' function Resolve-RoamerPath { $candidates = New-Object System.Collections.Generic.List[string] $appPathKeys = @( 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Roamer.exe', 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\App Paths\Roamer.exe' ) foreach ($key in $appPathKeys) { try { $value = (Get-ItemProperty -Path $key -ErrorAction Stop).'(default)' if (-not [string]::IsNullOrWhiteSpace($value)) { $candidates.Add($value) } } catch { } } $wellKnownPaths = @( (Join-Path ${env:ProgramFiles} 'Autodesk\Navisworks Manage 2026\Roamer.exe'), (Join-Path ${env:ProgramFiles(x86)} 'Autodesk\Navisworks Manage 2026\Roamer.exe'), (Join-Path ${env:ProgramFiles} 'Autodesk\Navisworks Simulate 2026\Roamer.exe'), (Join-Path ${env:ProgramFiles(x86)} 'Autodesk\Navisworks Simulate 2026\Roamer.exe') ) | Where-Object { $_ } foreach ($path in $wellKnownPaths) { $candidates.Add($path) } foreach ($candidate in $candidates | Select-Object -Unique) { if (-not [string]::IsNullOrWhiteSpace($candidate) -and (Test-Path $candidate)) { return [System.IO.Path]::GetFullPath($candidate) } } throw '找不到 Roamer.exe。请确认 Navisworks Manage 2026 已安装。' } function Resolve-DefaultModelPath { if (-not (Test-Path $defaultsFilePath)) { return $null } try { $defaults = Get-Content $defaultsFilePath -Raw | ConvertFrom-Json $defaultModelPath = [string]$defaults.defaultModelPath if ([string]::IsNullOrWhiteSpace($defaultModelPath)) { return $null } $resolvedPath = [System.IO.Path]::GetFullPath($defaultModelPath) if (-not (Test-Path $resolvedPath)) { throw "默认模型文件不存在: $resolvedPath" } return $resolvedPath } catch { throw "读取默认测试配置失败: $($_.Exception.Message)" } } function Dismiss-RecoveryPromptIfPresent { param( [int]$TimeoutSeconds = 20 ) Add-Type -AssemblyName System.Windows.Forms | Out-Null $shell = New-Object -ComObject WScript.Shell # NW 启动恢复提示框标题关键词(覆盖“从自动保存重新载入”“是否打开之前保存的模型”等变体) $windowTitleKeywords = @( '自动保存', '保存的模型', '重新载入', '恢复' ) $deadline = (Get-Date).AddSeconds($TimeoutSeconds) while ((Get-Date) -lt $deadline) { foreach ($keyword in $windowTitleKeywords) { try { # AppActivate 支持子串匹配,激活标题包含关键词的窗口 if ($shell.AppActivate($keyword)) { Start-Sleep -Milliseconds 300 [System.Windows.Forms.SendKeys]::SendWait('%N') Write-Host "已自动选择“否”以跳过恢复提示框(关键词: $keyword)。" return } } catch { } } Start-Sleep -Milliseconds 300 } } function Clear-NavisworksAutoSave { # 清理 NW 自动保存文件:NW 启动时检测到 AutoSave 残留会弹“是否打开之前保存的模型” # 提示框并拦截命令行打开请求。测试环境提前清理可彻底避免弹窗(测试前先正常退出 NW 以保存用户数据)。 $autoSaveDir = Join-Path $env:APPDATA 'Autodesk\Navisworks Manage 2026\AutoSave' if (Test-Path $autoSaveDir) { $removedCount = (Get-ChildItem $autoSaveDir -File -ErrorAction SilentlyContinue | Remove-Item -Force -ErrorAction SilentlyContinue | Measure-Object).Count Write-Host "已清理 Navisworks 自动保存文件(避免恢复提示框): $autoSaveDir" } } if ([string]::IsNullOrWhiteSpace($ModelPath)) { $ModelPath = Resolve-DefaultModelPath } if (-not [string]::IsNullOrWhiteSpace($ModelPath)) { $ModelPath = [System.IO.Path]::GetFullPath($ModelPath) if (-not (Test-Path $ModelPath)) { throw "模型文件不存在: $ModelPath" } } $roamerPath = Resolve-RoamerPath $existingProcess = Get-Process Roamer -ErrorAction SilentlyContinue | Select-Object -First 1 $env:TRANSPORTPLUGIN_TEST_AUTOMATION = '1' if ($existingProcess) { Write-Host ("Navisworks 已在运行,PID={0}" -f $existingProcess.Id) if (-not [string]::IsNullOrWhiteSpace($ModelPath)) { # 通过文件关联请求打开模型(Start-Process 传参对 NW 2026 不可靠) Start-Process -FilePath $ModelPath | Out-Null Write-Host ("已请求 Navisworks 打开模型: {0}" -f $ModelPath) } Dismiss-RecoveryPromptIfPresent -TimeoutSeconds 30 Write-Host '提示: 当前测试 HTTP 服务在插件 DockPane OnLoaded 中启动,首次测试前请确保插件面板已打开。' exit 0 } # 启动前清理自动保存文件,避免 NW 弹出恢复提示框(弹窗会拦截命令行打开模型) Clear-NavisworksAutoSave if (-not [string]::IsNullOrWhiteSpace($ModelPath)) { # 直接通过文件关联启动并打开模型(NW 2026 命令行传参打开文件不可靠) $startProcess = Start-Process -FilePath $ModelPath -PassThru $processId = $startProcess.Id Write-Host ("Navisworks 启动中(文件关联),PID={0}" -f $processId) } else { $process = Start-Process -FilePath $roamerPath -PassThru $processId = $process.Id Write-Host ("Navisworks 启动中,PID={0}" -f $processId) } $deadline = (Get-Date).AddSeconds(30) do { Start-Sleep -Milliseconds 500 $running = Get-Process -Id $processId -ErrorAction SilentlyContinue } while (-not $running -and (Get-Date) -lt $deadline) if (-not $running) { throw 'Navisworks 启动超时,30 秒内未检测到 Roamer.exe 进程。' } # 兜底:清理 AutoSave 后通常无恢复弹窗;短超时单次处理可能出现的其他提示框 Dismiss-RecoveryPromptIfPresent -TimeoutSeconds 3 Write-Host ("Navisworks 已启动: {0}" -f $roamerPath) if (-not [string]::IsNullOrWhiteSpace($ModelPath)) { Write-Host ("已打开模型参数: {0}" -f $ModelPath) } Write-Host '提示: 当前测试 HTTP 服务在插件 DockPane OnLoaded 中启动,首次测试前请确保插件面板已打开。'