#Requires -RunAsAdministrator #Requires -Version 5.1 [CmdletBinding()] param( [string]$Solution = $null ) $ErrorActionPreference = 'Continue' . "$PSScriptRoot\tc-common.ps1" if (-not $Solution) { $Solution = $script:DefaultSolution } New-Log $script:DefaultLogDir $LogFile = Join-Path $script:DefaultLogDir "check-state.log" function Write-Log($Message) { $line = "[{0}] {1}" -f (Get-Date -Format 'HH:mm:ss'), $Message Write-Host $line Add-Content -Path $LogFile -Value $line -Encoding UTF8 } # Load TwinCAT.Ads $adsDll = 'C:\Program Files (x86)\Beckhoff\TwinCAT\3.1\Components\Base\v170\TwinCAT.Ads.dll' try { Add-Type -Path $adsDll -ErrorAction Stop Write-Log "TwinCAT.Ads loaded from $adsDll" } catch { Write-Log "FATAL: Cannot load TwinCAT.Ads: $_" exit 1 } # Helper to bind to running XAE DTE via ROT function Get-XaeDte { Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; public class XaeRot { [DllImport("ole32.dll")] static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot); [DllImport("ole32.dll")] static extern int CreateBindCtx(int reserved, out IBindCtx ppbc); public static object GetDte(string match) { IRunningObjectTable rot; IBindCtx bc; GetRunningObjectTable(0, out rot); CreateBindCtx(0, out bc); IEnumMoniker em; rot.EnumRunning(out em); IMoniker[] mons = new IMoniker[1]; IntPtr fetched = IntPtr.Zero; while (em.Next(1, mons, fetched) == 0) { string name; mons[0].GetDisplayName(bc, null, out name); if (name.IndexOf(match, StringComparison.OrdinalIgnoreCase) >= 0) { object o; rot.GetObject(mons[0], out o); return o; } } return null; } } '@ -ReferencedAssemblies System.Runtime.InteropServices return [XaeRot]::GetDte('TcXaeShell.DTE') } function Read-Ads($NetId, $Port, $IGrp, $IOff, $Len) { $c = New-Object TwinCAT.Ads.TcAdsClient try { $c.Connect($NetId, $Port) $buf = New-Object byte[] $Len $n = $c.Read([uint32]$IGrp, [uint32]$IOff, $buf, 0, $Len) $hex = [BitConverter]::ToString($buf, 0, $n) return "OK n=$n : $hex" } catch { return "ERR: $($_.Exception.Message)" } finally { $c.Dispose() } } Write-Log "=== TwinCAT State Check ===" # Try to bind to running XAE DTE $dte = Get-XaeDte if (-not $dte) { Write-Log "No running XAE DTE found. Creating a new one..." try { $dte = New-Object -ComObject TcXaeShell.DTE.17.0 -ErrorAction Stop $dte.MainWindow.Visible = $true } catch { Write-Log "FATAL: Cannot create DTE: $_" exit 1 } } if (-not $dte.Solution.IsOpen) { Write-Log "Opening solution $Solution" try { $dte.Solution.Open($Solution) for ($i = 1; $i -le 120; $i++) { Start-Sleep -Seconds 1 if ($dte.Solution.IsOpen) { break } } } catch { Write-Log "Solution.Open error: $_" } } Write-Log "Solution open: $($dte.Solution.IsOpen)" Write-Log "Solution path: $($dte.Solution.FullName)" $sysMgr = $null for ($i = 1; $i -le 40; $i++) { try { $sysMgr = $dte.Solution.Projects.Item(1).Object if ($sysMgr) { break } } catch {} Start-Sleep -Seconds 2 } if (-not $sysMgr) { Write-Log "FATAL: Cannot get SysManager" exit 1 } Write-Log "SysManager obtained" $targetNetId = '169.254.176.217.1.1' $platform = 'TwinCAT RT (x64)' try { $sysMgr.SetTargetNetId($targetNetId); Write-Log "SetTargetNetId $targetNetId OK" } catch { Write-Log "SetTargetNetId error: $_" } try { $sysMgr.ConfigurationManager.ActiveTargetPlatform = $platform; Write-Log "ActiveTargetPlatform set to $platform" } catch { Write-Log "Set platform error: $_" } Start-Sleep -Seconds 3 # Read state before activation Write-Log "--- State BEFORE activation ---" try { Write-Log "IsTwinCATStarted = $($sysMgr.IsTwinCATStarted)" } catch { Write-Log "IsTwinCATStarted error: $_" } try { Write-Log "CurrentMode = $($sysMgr.CurrentMode)" } catch { Write-Log "CurrentMode error: $_" } try { Write-Log "TargetNetId = $($sysMgr.ConfigurationManager.ActiveConfiguration.TargetNetId)" } catch { Write-Log "TargetNetId error: $_" } try { Write-Log "ActivePlatform = $($sysMgr.ConfigurationManager.ActiveTargetPlatform)" } catch { Write-Log "ActivePlatform error: $_" } # Activate Write-Log "Activating configuration..." try { $sysMgr.ActivateConfiguration(); Write-Log "ActivateConfiguration OK" } catch { Write-Log "ActivateConfiguration error: $_" } Start-Sleep -Seconds 5 # Restart runtime to Run mode Write-Log "Restarting TwinCAT runtime..." try { $sysMgr.StartRestartTwinCAT(); Write-Log "StartRestartTwinCAT OK" } catch { Write-Log "StartRestartTwinCAT error: $_" } Start-Sleep -Seconds 10 # Read state after restart Write-Log "--- State AFTER activation/restart ---" try { Write-Log "IsTwinCATStarted = $($sysMgr.IsTwinCATStarted)" } catch { Write-Log "IsTwinCATStarted error: $_" } try { Write-Log "CurrentMode = $($sysMgr.CurrentMode)" } catch { Write-Log "CurrentMode error: $_" } try { $msgs = $sysMgr.GetLastErrorMessages(); Write-Log "LastErrorMessages = $msgs" } catch { Write-Log "GetLastErrorMessages error: $_" } # ADS diagnostics Write-Log "--- ADS diagnostics ---" Write-Log "System ADS state (169.254.176.217.1.1, port 65535, iGrp 0x0, iOff 0, 4 bytes): $(Read-Ads '169.254.176.217.1.1' 65535 0 0 4)" Write-Log "EtherCAT master 1 state (169.254.176.217.2.1, port 65535, iGrp 0x9, iOff 0, 32 bytes): $(Read-Ads '169.254.176.217.2.1' 65535 0x9 0 32)" # Try to export EtherCAT master online XML try { $io = $sysMgr.LookupTreeItem('TIID') $ecat = $null for ($j = 1; $j -le [int]$io.ChildCount; $j++) { try { $ch = $io.Child($j) if ([int]$ch.ItemSubType -eq 111) { $ecat = $ch; break } } catch {} } if ($ecat) { Write-Log "EtherCAT master found: $($ecat.Name)" $xml = $ecat.ProduceXml($true) $xmlFile = Join-Path $script:DefaultLogDir 'check-state_master.xml' [System.IO.File]::WriteAllText($xmlFile, $xml, [System.Text.Encoding]::UTF8) Write-Log "Master Online XML saved: $xmlFile ($($xml.Length) bytes)" Write-Log "Enumerating configured boxes under master:" for ($j = 1; $j -le [int]$ecat.ChildCount; $j++) { try { $b = $ecat.Child($j) Write-Log " Box[$j]: name='$($b.Name)' subtype=$($b.ItemSubType)" } catch {} } } else { Write-Log "No EtherCAT master found under TIID" } } catch { Write-Log "EtherCAT XML error: $_" } Write-Log "=== Check complete ==="