#Requires -Version 5.1 <# .SYNOPSIS Open TwinCAT solution via DTE, ActivateConfiguration + StartRestartTwinCAT, poll for Run. .DESCRIPTION Invisible DTE automation path proven in free/activate-and-run.ps1. #> param( [string]$Solution = 'C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Primary\TwinCATProject1.sln', [string]$LogFile = 'C:\Users\tonycao\work\twincat3-auto-cli\TwinCAT_EL6695_Primary\Logs\tc-dte-activate-run.log' ) $ErrorActionPreference = 'Continue' function Log($m) { $line = (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') + ' ' + $m Add-Content -Path $LogFile -Value $line -Encoding utf8 -ErrorAction SilentlyContinue Write-Host $line } New-Item -ItemType Directory -Force -Path (Split-Path $LogFile) | Out-Null # Load TwinCAT.Ads.dll (same working copy used by tc-ads-readstate) $adsDll = 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll' Add-Type -Path $adsDll -ErrorAction SilentlyContinue function Get-State { try { $c = New-Object TwinCAT.Ads.TcAdsClient $c.Connect('169.254.176.217.1.1', 10000) $s = $c.ReadState() $c.Dispose() return "$($s.AdsState)" } catch { return "ERR: $($_.Exception.Message)" } } function Read-PortState($port) { try { $c = New-Object TwinCAT.Ads.TcAdsClient $c.Connect('169.254.176.217.1.1', $port) $s = $c.ReadState() $c.Dispose() return "$($s.AdsState)" } catch { return "ERR: $($_.Exception.Message)" } } Log '=== tc-dte-activate-run start ===' Log ("state before: " + (Get-State)) try { $dte = New-Object -ComObject TcXaeShell.DTE.17.0 } catch { Log ("DTE 17.0 failed, trying 15.0: " + $_) $dte = New-Object -ComObject TcXaeShell.DTE.15.0 } $dte.SuppressUI = $true $dte.MainWindow.Visible = $false Log "Opening solution: $Solution" $dte.Solution.Open($Solution) for ($i = 1; $i -le 120; $i++) { Start-Sleep -Seconds 1 if ($dte.Solution.IsOpen) { Log ("IsOpen=True after " + $i + "s"); break } } if (-not $dte.Solution.IsOpen) { throw 'Solution did not open' } Log 'Waiting 40s for project tree ...' Start-Sleep -Seconds 40 $project = $dte.Solution.Projects.Item(1) $sm = $project.Object Log ("SysManager type: " + $sm.GetType().FullName) try { $sm.SetTargetNetId('169.254.176.217.1.1') Log 'SetTargetNetId OK' } catch { Log ("SetTargetNetId warning: " + $_.Exception.Message) } # Step 1: ActivateConfiguration $actOK = $false for ($a = 1; $a -le 3; $a++) { try { $sm.ActivateConfiguration() Log "ActivateConfiguration OK (attempt $a)" Start-Sleep -Seconds 2 try { $err = $sm.GetLastErrorMessages(); if ($err) { Log "ActivateConfiguration messages: $err" } } catch { Log ("GetLastErrorMessages err: " + $_.Exception.Message) } $actOK = $true break } catch { Log ("ActivateConfiguration err (attempt $a): " + $_.Exception.Message) Start-Sleep -Seconds 2 try { $err = $sm.GetLastErrorMessages(); if ($err) { Log "ActivateConfiguration messages: $err" } } catch {} Start-Sleep -Seconds 15 } } # Step 2: enter Run via StartRestartTwinCAT if ($actOK) { Log 'Waiting 10s, then StartRestartTwinCAT...' Start-Sleep -Seconds 10 try { $r = $sm.StartRestartTwinCAT() Log ("StartRestartTwinCAT() returned: " + $r) Start-Sleep -Seconds 2 try { $err = $sm.GetLastErrorMessages(); if ($err) { Log "StartRestartTwinCAT messages: $err" } } catch { Log ("GetLastErrorMessages err: " + $_.Exception.Message) } } catch { Log ("StartRestartTwinCAT err: " + $_.Exception.Message) try { $err = $sm.GetLastErrorMessages(); if ($err) { Log "StartRestartTwinCAT messages: $err" } } catch {} } } # Step 3: poll for Run for ($i = 1; $i -le 12; $i++) { Start-Sleep -Seconds 5 $st = Get-State Log ("state +" + ($i*5) + "s: " + $st) if ($st -eq 'Run') { break } } # Check PLC port 851 Log ("port 851 state: " + (Read-PortState 851)) # Save and quit try { $dte.Solution.SaveAll(); Log 'SaveAll OK' } catch { Log ("SaveAll err: " + $_.Exception.Message) } try { $dte.Quit(); Log 'DTE quit' } catch { Log ("Quit err: " + $_.Exception.Message) } Log ("final state: " + (Get-State)) Log '=== tc-dte-activate-run end ==='