Setting up PowerShell for the Automation Interface

The TwinCAT Automation Interface uses COM objects, which place special demands on the PowerShell environment. The most important point is the threading model. The COM objects of the Automation Interface are registered in the Single-Threaded Apartment (STA) and can only be accessed correctly from an STA thread. However, PowerShell 7 runs by default in the Multi-Threaded Apartment (MTA). The STA requirement must therefore be explicitly met by creating a separate STA runspace. This article highlights the most important pitfall and how to avoid it.

Requirements

TwinCAT XAE and PowerShell 7.x must be installed.

Setting the STA mode

COM objects in the Automation Interface require STA (Single-Threaded Apartment). The STA model guarantees that all calls to a COM object are serialized and run on exactly one thread. That is exactly what the Automation Interface expects. If, on the other hand, the object is accessed from an MTA thread, errors such as RPC_E_SERVERCALL_RETRYLATER or unexpected marshalling issues may occur.

Since PowerShell 7 starts in MTA mode by default, a separate STA runspace is created. A runspace is created via RunspaceFactory, with its ApartmentState explicitly set to "STA". The setting ThreadOptions = "ReuseThread" ensures that all subsequent calls use the same thread. This is absolutely necessary because an STA-COM object may only be accessed by the thread that created it. The actual COM code is then executed within this STA runspace via AddScript({ ... }).Invoke():

$ps = [PowerShell]::Create()
$rs = [RunSpaceFactory]::CreateRunspace()
$rs.ApartmentState = "STA"
$rs.ThreadOptions = "ReuseThread"
$rs.Open()
$ps.Runspace = $rs
$ps.AddScript({
    $dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("TcXaeShell.DTE.17.0")
    $project = $dte.Solution.Projects.Item(1)
    $project.Object  # ITcSysManager
}).Invoke()