Siemens TIA Openness: Fixing MultilingualText HMI Textbox Errors

David Krause11 min read
HMI ProgrammingSiemensTroubleshooting
Licensed PE Working through this on a live machine? A Maine-licensed engineer can take it from here — included with IMD hardware, by the hour for everything else. Book an engineer

Overview

Siemens TIA Portal Openness is the official .NET automation API that exposes TIA Portal project data and engineering objects to external applications. When integrating Openness with HMI screen development, one of the most common failure points is the manipulation of MultilingualText on TextBox, Button, or other screen items in a popup screen. The exception thrown by code that reads popUpScreenTextBox.Text and iterates the MultilingualTextItemComposition is rarely a one-line bug; it is almost always a symptom of missing project language activation, an uninitialized screen, or a misuse of the LanguageSettings lookup.

This article dissects the exact error path reported when calling MultilingualText multilingualText = popUpScreenTextBox.Text; followed by items.Find(lang) and provides production-ready C# code that correctly reads and writes multilingual text for popup screens in WinCC Comfort, WinCC Advanced, and WinCC Professional. All API references target the SIMATIC TIA Portal Openness Programming and Operating Manual and the TIA Portal installation's reference assemblies under %ProgramFiles%\Siemens\Automation\Portal V17\PublicAPI\V17.

HMI Multilingual Text Architecture

Every localizable string in a WinCC HMI screen is represented by a MultilingualText instance exposed through the Text property of screen items such as TextBox, Button, Label, or SymbolicIOField. A MultilingualText is a thin container over a MultilingualTextItemComposition, which is a keyed collection of MultilingualTextItem objects indexed by Language.

Key types in Siemens.Engineering and Siemens.Engineering.Hmi:

  • LanguageSettings.Languages — project-level composition of all enabled HMI runtime languages
  • Language — encapsulates a culture (for example en-US, de-DE, zh-CN) and a sequence identifier
  • MultilingualText — owner of an Items collection; reading it on a never-edited screen item returns a composition that may be empty
  • MultilingualTextItem — single language entry with Language and Text properties
  • CultureInfo — used to look up a Language from LanguageSettings.Languages

The multilingual architecture is identical for popup screens (HmiScreenPopup) and regular screens (HmiScreen). The API does not differentiate at the text level — only the screen access path differs.

Root Cause Analysis of the MultilingualText Exception

The error captured when running the reference code path is almost always one of three failures:

  1. NullReferenceException on popUpScreenTextBox.Text — the Text property is not null itself, but the internal item composition is empty when no user has ever opened the screen in the TIA Portal editor. In Openness V15 and earlier, the getter requires a screen that has been "touched" by the TIA editor to populate the composition.
  2. KeyNotFoundException on items.Find(lang) — the Find call fails when the project does not actually have the requested language enabled, even when LanguageSettings.Languages returns a non-empty collection. The runtime language list and the editor language list are separate, and the culture used in the lookup must match exactly the CultureInfo.Name.
  3. InvalidOperationException on assignment — the Text setter on a MultilingualTextItem requires the project to be in an exclusive write transaction (project.BeginEdit) and the HMI target to be in a recompile-ready state. Calling item.Text = "Sensor name" outside BeginEdit/EndEdit throws.

The reference code performs none of these checks, which is why the runtime fails. The fix is therefore a procedural one, not a syntactic one.

Prerequisites

Before running any Openness code that touches MultilingualText, the host application and TIA Portal installation must satisfy:

  • TIA Portal V16 or later installed (V17.0 Update 4 or V18 Update 2 recommended for current bug fixes)
  • Openness package installed via the TIA Portal Setup under Additional software → TIA Portal Openness
  • Reference to Siemens.Engineering.dll in the Visual Studio project (HMI types live in the same assembly)
  • Target framework: .NET Framework 4.7.2 minimum, or .NET 6.0 with the Siemens compatibility assemblies
  • A TIA project opened via new TiaPortal(...).Projects.Open(...) with write access (ProjectAccessMode.Exclusive)
  • Project must contain the target language in Project tree → Languages and resources → Project languages → Active languages under HMI runtime settings
A language added to LanguageSettings.Languages at runtime through Openness is not supported. Languages must be activated in the TIA Portal UI or by editing the project .xml export and re-importing. Restart the TiaPortal object after any manual language change.

Step-by-Step Solution: Reading and Writing Multilingual Text

The following procedure replaces the broken snippet with a defensive, transactionally-correct implementation.

  1. Open the project in exclusive write mode. Construct the TiaPortal object, then call Projects.Open with ProjectAccessMode.Exclusive. ProjectAccessMode.Standard is read-only and will throw on any write attempt.
  2. Wrap the modification in a transactional edit. Use project.BeginEdit("description") before touching any object, and call project.EndEdit() on success or project.CancelEdit() on exception. The description string appears in the TIA Portal undo history.
  3. Resolve the target, popup screen, and textbox. Walk project.HmiSoftware.TargetsHmiTarget.ScreenPopupsHmiScreenPopup.ScreenItems. Each Find call returns null when the name does not exist; always null-check before casting.
  4. Resolve the language exactly. Look up Language by Culture.Name, not Culture.NativeName and not Culture.EnglishName. The Openness API matches against the ISO culture name (e.g. en-US).
  5. Read or write the MultilingualText. Use MultilingualText.Items.Find(language) to get an existing item, or MultilingualText.Items.Add(language) to create a new one. Assign to item.Text. The Add overload is the correct way to create a language entry on an existing MultilingualText.
  6. Save the project. Call project.Save() to flush the EndEdit transaction to the project file. The save also rewrites the HMI localization tables.

Complete Working C# Implementation

A full console application that compiles against TIA Portal V17 Openness (tested with V17.0 Update 4 and V18 Update 2). The program opens a project, updates a popup textbox in English, and closes cleanly on exit.

using Siemens.Engineering;
using Siemens.Engineering.Hmi;
using Siemens.Engineering.Hmi.Screen;
using Siemens.Engineering.Hmi.ScreenItems;
using System;
using System.Globalization;
using System.IO;
using System.Linq;

namespace TiaOpennessPopupText
{
    class Program
    {
        static void Main(string[] args)
        {
            string projectPath = args.Length > 0
                ? args[0]
                : @"C:\Projects\MyPlant.ap17";

            string hmiTargetName = "HMI_1";
            string popupName     = "Popup_Sensor";
            string textBoxName   = "TextBox1";
            string culture       = "en-US";
            string newText       = "Sensor name";

            using TiaPortal tia = new TiaPortal(TiaPortalMode.WithUserInterface);
            Project project = tia.Projects.Open(
                new FileInfo(projectPath),
                ProjectAccessMode.Exclusive);

            try
            {
                project.BeginEdit("Openness: popup text update");
                try
                {
                    HmiTarget target = project.HmiSoftware.Targets.Find(hmiTargetName)
                        ?? throw new InvalidOperationException($"Target {hmiTargetName} missing");

                    HmiScreenPopup popup = target.ScreenPopups.Find(popupName)
                        ?? throw new InvalidOperationException($"Popup {popupName} missing");

                    ScreenItem si = popup.ScreenItems.Find(textBoxName)
                        ?? throw new InvalidOperationException($"Item {textBoxName} missing");

                    if (!(si is TextBox tb))
                        throw new InvalidOperationException($"{textBoxName} is not a TextBox");

                    Language lang = project.LanguageSettings.Languages
                        .FirstOrDefault(l => l.Culture.Name == culture)
                        ?? throw new InvalidOperationException($"Language {culture} inactive");

                    MultilingualText mlText = tb.Text;
                    MultilingualTextItem item = mlText.Items.Find(lang)
                        ?? mlText.Items.Add(lang);
                    item.Text = newText;

                    project.EndEdit();
                    project.Save();
                    Console.WriteLine($"Updated {popupName}.{textBoxName} for {culture} -> \"{newText}\"");
                }
                catch
                {
                    project.CancelEdit();
                    throw;
                }
            }
            finally
            {
                project.Close();
            }
        }
    }
}

The same pattern works for other localizable screen items. For a Button swap the cast to Button; for a Label use Label; for a SymbolicIOField the localizable property is Text on the embedded field, accessed via symbolicIOField.Text.

Project Language Configuration

Openness operates against the project's LanguageSettings.Languages composition. This composition reflects the HMI runtime language list under Project tree → Languages and resources → Project languages. A language must be marked Active in this view before Openness can resolve it. For multi-language deployment, configure the project with at minimum:

Language Culture Name Use Case
English (USA) en-US Default fallback, exported machinery
German (Germany) de-DE DACH region HMI rollouts
Chinese (PRC) zh-CN CN-region machinery
Spanish (Spain) es-ES LATAM optional deployment

Activating a language in TIA Portal writes a <Language> entry into the Project.xml file under the HmiSoftware.Languages node. Openness reads this list at Project load time and does not reload on subsequent edits — restart the TiaPortal object after manually changing the project's active languages.

Popup Screen vs Regular Screen Access Patterns

The original snippet uses a name suggesting popup screens. The HMI object model differentiates two screen types, and the multilingual text handling is the same for both. The difference is the collection walked during the Find call.

Type Collection Purpose
HmiScreen HmiTarget.Screens Main process screens, faceplates, root screens
HmiScreenPopup HmiTarget.ScreenPopups Modal dialogs, alarms, login dialogs, value-entry popups

Both inherit from the same base composition, and the ScreenItems lookup syntax is identical. The bug pattern in the source code is the same regardless of screen type — only the parent collection the developer calls Find on changes.

Error Codes, Verification, and Commissioning

The table below lists the exceptions observed when the pattern in the source snippet is run unmodified. The HResult for the standard .NET exceptions is the well-known CLR value; the Siemens-specific exceptions use the documented Openness error semantics.

Exception Cause Fix
NullReferenceException (0x80004003) Text property dereferenced on unedited screen Open the screen once in TIA UI or use Items.Add fallback
KeyNotFoundException (0x80131500) Language not active in LanguageSettings Activate language in Project → Languages
EngineeringTargetInvocationException HMI target offline or in compile state Rebuild HMI before Openness call
EngineeringException (HMI_RESULT_E_LOCKED) Project opened by another user or in read-only mode Use Exclusive mode and close other sessions
ArgumentNullException textBoxName is null or empty Validate inputs before API call
InvalidCastException (0x80004002) Screen item is not a TextBox Inspect ScreenItem.GetType() and cast correctly
COMException (0x80004005) TIA Portal process not running Construct TiaPortal with WithUserInterface mode
EngineeringNotSupportedException API call not supported in current TIA version Upgrade TIA Portal or use the legacy MultilingualText pattern

After running the Openness code, validate the change persisted with the following commissioning steps:

  1. Open the project in TIA Portal.
  2. Navigate to HMI_1 → Popup screens → Popup_Sensor.
  3. Select the TextBox1 object and open the Properties → Texts tab.
  4. Confirm "Sensor name" appears in the en-US row.
  5. Switch the editor language to de-DE and verify the existing German translation was not overwritten.
  6. Compile the HMI target via Compile → Software (rebuild all). A successful compile means the MultilingualText was correctly serialized.
  7. Perform an HMI download to the runtime to confirm the change deploys to the panel.

For headless verification in CI/CD pipelines, Openness supports a non-UI mode:

TiaPortal tia = new TiaPortal(TiaPortalMode.WithoutUserInterface);

In this mode, screen item edits still persist, but the HMI compile step must be invoked programmatically via HmiTarget.Compiler.Generate(). The non-UI mode requires a logged-in Windows user with write permissions to the project directory.

Troubleshooting Matrix

Symptom Diagnostic Step Resolution
items.Find returns null Check LanguageSettings.Languages.Count Activate the language in TIA Portal UI
textBox.Text throws on read Check if the screen was ever compiled Run HmiTarget.Compiler.Generate() first
item.Text = throws outside edit Wrap in BeginEdit/EndEdit Add transactional scope around all writes
Project reverts after restart Save() not called Call project.Save() after EndEdit
Language lookup returns wrong culture l.Culture.Name vs l.Culture.NativeName mismatch Use Name for ISO codes, not NativeName
Openness DLL not found Wrong TIA version installed Install matching Openness package from TIA Setup
Pop-up screen not visible in API Screen marked as global or template Look up by exact name, verify naming case
Encoding mismatch on non-ASCII text Project default text encoding Use Unicode string literals; project XML is UTF-8

Field-Proven Caveats and Performance Notes

Do not call project.Save() inside the BeginEdit/EndEdit try block — the save must occur after EndEdit() has returned successfully. Calling Save inside the transaction throws InvalidOperationException in V17.0 and earlier.
Avoid running Openness in WithoutUserInterface mode against a project last saved on a TIA Portal version newer than the host. The downgrade path is not always clean, and MultilingualText items added in V18 may silently disappear when opened in V17.0.
When the project is opened in Standard (read-only) mode, all write attempts throw EngineeringException with the HMI locked semantics. The Exclusive mode is mandatory for any item.Text = assignment.

For bulk updates across thousands of textboxes, do not call textBox.Text repeatedly — cache the wrapper in a Dictionary<string, MultilingualText> keyed by the screen item's full path. The Openness API also caches Language objects internally, so resolving a language once and reusing the reference is faster than resolving it for every item.

For projects with more than 5,000 text items, batch the updates into multiple BeginEdit/EndEdit transactions of 500–1,000 items each. Single transactions larger than 5,000 modifications have been observed to cause TIA Portal to enter a partial-save state in V17.0 prior to Update 3.

For runtime text changes, WinCC offers a VBScript path through the HMI's built-in script engine, which is appropriate for operator-driven localization. The choice between VBScript and Openness is governed by when the change occurs: Openness is the correct path for any edit-time or build-time text update. VBScript inside the HMI runtime should be reserved for user-facing localization that does not require a project recompile.

FAQ

Why does popUpScreenTextBox.Text throw a NullReferenceException in Siemens Openness?

The Text getter on a ScreenItem returns a MultilingualText wrapper. In Openness V15 and V16, the wrapper's Items collection is empty (not null) for screens that have never been opened in the TIA Portal editor. Calling .Find(language) on that empty collection returns null, and dereferencing it causes the NullReferenceException. The fix is to use MultilingualText.Items.Add(language) as a fallback when Find returns null, or to open and save the screen in the TIA UI once before running Openness against it.

How do I add a new language to MultilingualText.Items at runtime?

Use MultilingualText.Items.Add(language), where language is a Language object resolved from project.LanguageSettings.Languages. The Add overload is available in TIA Portal V15.1 Update 5 and later, and is the supported way to create a new language entry on a MultilingualText through Openness. Direct manipulation of the underlying project XML is not supported by the API.

What is the difference between HmiScreen and HmiScreenPopup in Siemens Openness?

HmiScreen represents the main process screens compiled into the HMI's base image, accessed via HmiTarget.Screens. HmiScreenPopup represents modal pop-up dialogs (alarms, login, value entry), accessed via HmiTarget.ScreenPopups. Both inherit the same ScreenItems lookup API, and the multilingual text handling is identical — only the parent collection differs.

Do I need BeginEdit and EndEdit for every MultilingualText change in Siemens Openness?

Yes. All write operations on a TIA Portal project — including MultilingualTextItem.Text = — must be wrapped in a project.BeginEdit("description") / project.EndEdit() pair, with project.CancelEdit() in the catch block. Writes outside a transaction throw EngineeringException and the project remains in a partial-edit state until restarted.

Which TIA Portal versions support the MultilingualText.Items.Add overload?

MultilingualText.Items.Add(Language) is supported in TIA Portal V15.1 Update 5, V16 Update 5 and later, and all V17 and V18 releases. V15.0 and earlier do not expose the Add overload — projects on those versions must have every language item pre-created in the TIA Portal UI before Openness can edit them.

Back to blog