addin-operations
TIA Portal Add-In development in Visual Studio Code: creating Add-In C# projects, adding Add-In templates, compiling and…
Internal reference skill — do NOT load directly from user queries.
Claude Code
$ npx -y skills add Czarnak/totally-integrated-claude --skill tia-csharp-common --agent claude-code
Codex
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a codex -y
Cursor
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a cursor -y
Gemini CLI
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a gemini-cli -y
GitHub Copilot
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a github-copilot -y
OpenCode
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a opencode -y
Windsurf
$ npx skills add Czarnak/totally-integrated-claude --skill tia-csharp-common -a windsurf -y
name: tia-csharp-common description: Internal reference skill — do NOT load directly from user queries. license: MIT
Source: TIA Portal Openness General Functions Manual (03/2026, V21); V21 IntelliSense XML documentation files (PublicAPI\V21\net48\*.xml)
---
V21 splits the API across multiple DLLs instead of a single `Siemens.Engineering.dll`. Every project needs `Siemens.Engineering.Base.dll`; add domain DLLs as required. Referencing the wrong DLL (or omitting one) causes `TypeLoadException` at runtime.
> **Full mapping:** See `references/assembly-namespace-map.md` for the V21 > namespace → DLL → domain skill table, cross-assembly warnings, and csproj patterns.
Only import what is actually used. Commented `using` blocks for each assembly (Base, Step7, WinCC, Startdrive, Safety) are in `references/assembly-namespace-map.md` under "Common `using` blocks by assembly".
---
> **Not needed for Add-Ins.** TIA Portal loads Add-In assemblies via its own loader. > This section applies only to standalone console/desktop Openness applications.
When using the `AssemblyResolve` approach, register the event before any Openness type is referenced. This includes method parameters, return types, and class properties — not just method bodies. A correctly configured `app.config` binding is an alternative.
Recommended pattern: register in a static constructor of `Program`, then move all Openness code to a separate class so the resolver is active before those classes are loaded.
internal static class Program
{
// Register resolver at earliest possible point
static Program()
{
AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
}
public static void Main()
{
// All Openness code must be in a separate class
var app = new OpennessApp();
app.Run();
}
private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
{
// Read install path from registry (recommended) or hardcode for simple tools
string opennessFolder = GetOpennessInstallPath(); // implement per project
AssemblyName requestedName = new AssemblyName(args.Name);
string filePath = Path.Combine(opennessFolder,
string.Concat(requestedName.Name, ".dll"));
if (!requestedName.Name.StartsWith("Siemens.Engineering.") ||
!File.Exists(filePath))
return null;
Assembly loaded = Assembly.LoadFrom(filePath);
if (requestedName.FullName != loaded.GetName().FullName)
throw new FileNotFoundException(
"TIA Portal Openness version does not match", filePath);
return loaded;
}
}**Key rules:**
`Startdrive.dll`, etc. per task. The resolver handles all of them automatically because it matches any name starting with `Siemens.Engineering.`.
`HKLM\SOFTWARE\Siemens\Automation\InstalledApps\Totally Integrated Automation Portal V21` (value `INSTALLPATH`) rather than hardcoding it.
**Registry-based path discovery:**
private static string GetOpennessInstallPath()
{
using (var key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
@"SOFTWARE\Siemens\Automation\InstalledApps\Totally Integrated Automation Portal V21"))
{
string installPath = key?.GetValue("INSTALLPATH") as string;
if (string.IsNullOrEmpty(installPath))
throw new FileNotFoundException("TIA Portal V21 installation not found in registry.");
return Path.Combine(installPath, @"PublicAPI\V21\net48");
}
}**Alternative — app.config:** For stable installations where the path is known at build time, an `app.config` file with `<assemblyBinding>` / `<codeBase>` entries is a simpler option that requires no code. Use the `AssemblyResolve` event for tools that need to discover the install path at runtime.
---
Always use a `using` statement so the session is disposed on exit or exception:
internal class OpennessApp
{
public void Run()
{
using (TiaPortal tiaPortal = new TiaPortal(TiaPortalMode.WithUserInterface))
{
// All Openness work goes here
}
// TIA Portal is disposed (not necessarily closed) after this point
}
}**Modes:**
**Attaching to a running instance:**
// Attach to the first running TIA Portal process of this Openness version TiaPortal tiaPortal = TiaPortal.GetProcesses().First().Attach();
Use `GetProcesses()` when TIA Portal is already open and you do not want to start a new instance. Returns only processes from the same Openness version as the loaded assembly.
**Dispose vs. close:**
process is closed exter
An agent plugin for Siemens TIA Portal engineering automation, compatible with Claude Code, Codex, and GitHub Copilot in VS Code and Copilot CLI.
TIA Portal Add-In development in Visual Studio Code: creating Add-In C# projects, adding Add-In templates, compiling and…
Standalone skill for multi-perspective PLC code security and quality analysis. Triggers on: "review", "audit", "analyze",…
Manual, read-only prerequisite probe for TIA Portal V21 and its modular Openness API, with an optional Python TIA Scripting check.
C# Openness implementation of import/export and round-trip engineering.
Direct browser control via CDP for web interaction: automation, scraping, testing, screenshots, and site/app work. Also covers…
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling…