119 lines
3.8 KiB
PowerShell
119 lines
3.8 KiB
PowerShell
|
|
#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
|
||
|
|
}
|