#Requires -Version 5.1 <# .SYNOPSIS TwinCAT automation common functions. Sourced by all other scripts via . "$PSScriptRoot\tc-common.ps1" .DESCRIPTION Provides: - Get-Dte : create/attach TcXaeShell DTE COM object - Open-Solution : open .sln and wait for System Manager - Get-SysManager : extract ITcSysManager from the open project - Wait-Busy : poll SolutionBuild.BuildState until idle - Write-Log : timestamped console + file logging #> # ---- Defaults ---- $script:DefaultSolution = "C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Secondary\TwinCAT_EL6695_Secondary.sln" $script:DefaultTsproj = "C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Secondary\TwinCAT_EL6695_Secondary.tsproj" $script:DefaultLogDir = "C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Secondary\Logs" $script:DefaultTargetNetId = "169.254.176.217.1.1" # local TwinCAT-Intel $script:El6695Path = "TIID^设备 1 (EtherCAT)^模块 1 (EK1100)^模块 8 (EL6695)" # ---- Logging ---- function New-Log($dir) { New-Item -ItemType Directory -Path $dir -Force | Out-Null } function Write-Log { param([string]$Message, [string]$LogFile = "") $line = "[{0}] {1}" -f (Get-Date -Format 'HH:mm:ss'), $Message Write-Host $line if ($LogFile) { Add-Content -Path $LogFile -Value $line -Encoding UTF8 } } # ---- DTE ---- function Get-Dte { param([switch]$Visible) $dte = New-Object -ComObject TcXaeShell.DTE.17.0 -ErrorAction Stop # SysManager only initialises when the main window is visible. # SuppressUI=true prevents the project tree from loading. $dte.MainWindow.Visible = $true try { $dte.SuppressUI = $false } catch { } return $dte } function Open-Solution { param( [Parameter(Mandatory)][object]$Dte, [string]$Solution = $script:DefaultSolution, [int]$TimeoutSec = 120 ) Write-Log "Opening solution: $Solution" $Dte.Solution.Open($Solution) for ($i = 1; $i -le $TimeoutSec; $i++) { Start-Sleep -Seconds 1 if ($Dte.Solution.IsOpen) { Write-Log "Solution open after ${i}s" return $true } } return $false } function Get-SysManager { param([Parameter(Mandatory)][object]$Dte, [int]$TimeoutSec = 120) Write-Log "Waiting for System Manager..." Start-Sleep -Seconds 30 for ($i = 0; $i -lt 20; $i++) { try { $sysMgr = $Dte.Solution.Projects.Item(1).Object if ($sysMgr) { $dummy = $sysMgr.LookupTreeItem("TIID") Write-Log "SysManager ready after $($i) retries" return $sysMgr } } catch { Write-Log " SysManager retry $($i+1)/20: waiting 5s..." } Start-Sleep -Seconds 5 } Write-Log "SysManager not ready" return $null } function Wait-Busy { param([Parameter(Mandatory)][object]$Dte, [int]$TimeoutSec = 180) $start = Get-Date while (((Get-Date) - $start).TotalSeconds -lt $TimeoutSec) { $sb = $Dte.Solution.SolutionBuild $state = $sb.BuildState # 1=done, 2=in_progress $info = $sb.LastBuildInfo if ($state -eq 1) { return $info } Start-Sleep -Seconds 3 } Write-Log "Timeout waiting for build idle" return -1 } # ---- Tree item helpers ---- function Find-TreeItem { param([Parameter(Mandatory)][object]$SysMgr, [string[]]$Paths) foreach ($p in $Paths) { try { $item = $SysMgr.LookupTreeItem($p) if ($item) { return $item } } catch { } } return $null } function Find-Box { param([object]$Node, [string]$Pattern = "*EL6695*") foreach ($child in $Node) { if ($child.Name -like $Pattern) { return $child } $found = Find-Box -Node $child -Pattern $Pattern if ($found) { return $found } } return $null }