WinCC VBScript vs C Script: RT Shutdown and Tag Addressing

David Krause11 min read
SiemensTutorial / How-toWinCC
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

1. WinCC Scripting Architecture Overview

Siemens WinCC (SIMATIC WinCC V7.x and the TIA Portal WinCC Professional / Comfort / RT Advanced variants) exposes two distinct scripting engines to the developer:

  • VBScript (VBS) — interpreted, late-bound, and the only language allowed in user-defined menus, dynamic dialogs, and the global actions configured in the Graphics Designer that must reach user-interface elements.
  • ANSI-C — compiled, strongly typed, and the language used for picture-specific C actions, global C actions, and background polling tasks where predictable execution timing matters.

The two engines are not interchangeable. Menu editors, custom menu entries, and standard dynamic dialogs only accept VBScript, while some background triggers and project-wide hooks perform far better in C. Understanding this split is the foundation for resolving the three recurring issues in WinCC projects: stopping the Runtime from a menu, opening a picture from a menu, and reading/writing tags from a C script.

The WinCC Information System shipped with the installation (Start → SIMATIC → WinCC → WinCC Information System) is the authoritative reference for the C-API. The online portal at support.industry.siemens.com carries the latest manuals and the WinCC V7.5 SP2 / V8.0 manuals (entry ID 109973200 and 109811930) where every API call is documented.

2. VBScript vs ANSI-C: Where Each Language Runs

Editor / Trigger VBScript allowed? C allowed? Notes
User-defined menu (Menu → Configure) Yes No Hard limit in Graphics Designer
Button mouse action Yes Yes Either engine selectable
Picture events (Open / Close) Yes Yes Picture-level hooks
Global action (cyclic / tag trigger) Yes Yes Background processing
Dynamic dialog Yes (formula) No Direct tag / expression
Tag logging / alarm scripting No Yes C is the only choice

When a developer wants a clickable menu entry to do anything beyond toggling a tag through a dynamic dialog, VBScript is the only path. Trying to paste a C block into a menu property produces a compile error such as "Function expected / Unknown identifier". The workaround is therefore to place all logic in VBScript, or to use VBScript to invoke a compiled C function via the WinCC project DLL.

3. Shutting Down WinCC Runtime from a Menu

The standard WinCC RT shutdown call from VBScript is the HMIRuntime.Stop method, available since WinCC V7.0 SP3. Place the snippet below on the Mouse click event of the custom menu item:

' Menu → Configure → your custom entry → Mouse click (left) ' Triggers a clean shutdown of WinCC Runtime on the local station Sub OnClick(ByVal Item) Dim answer answer = MsgBox("Shut down WinCC Runtime?", vbYesNo + vbQuestion, "Confirm Exit") If answer = vbYes Then HMIRuntime.Stop End If End Sub

For projects where the user must be authenticated before the Runtime can be closed, gate the call on a WinCC user level:

Sub OnClick(Byval Item) If HMIRuntime.Authorization.Check("RT_Stop") = False Then MsgBox "Insufficient privileges to stop Runtime.", vbCritical Exit Sub End If HMIRuntime.Stop End Sub

For passivation-style shutdown (close the Runtime but keep the project in Configuration mode), use HMIRuntime.DeactivateRT. The full method list is in the WinCC V7.5 SP2 manual "Working with WinCC — VBScript", entry ID 109973200.

3.1 External Shutdown with CCStartStop.exe

When a separate tool (alarm dispatcher, third-party HMI scheduler, service-mode launcher) must stop the Runtime, use the bundled CCStartStop.exe located at %ProgramFiles%\Siemens\Automation\WinCC\bin\. The executable accepts the parameters /start, /stop, and /activate:


# Stop Runtime from a service or scheduled task
"C:\Program Files\Siemens\Automation\WinCC\bin\CCStartStop.exe" /stop

# Start Runtime back up (project on same station)
"C:\Program Files\Siemens\Automation\WinCC\bin\CCStartStop.exe" /start /project:MyProject

Return codes: 0 = success, 1 = project not found, 2 = access denied, 3 = Runtime already in requested state. Always run the executable under the same Windows account that owns the WinCC project to avoid error 2.

4. Opening a PictureScreen from a Custom Menu

The C-equivalent SSMOpenScreen cannot be called from a menu because menus reject C. The VBScript equivalent is HMIRuntime.BaseScreenName = "MyPicture.PDL" (for the base screen) or HMIRuntime.ActiveScreen for picture windows. For a direct screen change with a return-to-previous stack push, use HMIRuntime.Trace + ScreenItems("ScreenWindow").Screen = "...":

' Menu entry → Mouse click → open a picture in the primary screen window Sub OnClick(Byval Item) HMIRuntime.BaseScreenName = "Overview.PDL" End Sub ' Open in a named picture window (most common in modern projects) Sub OnClick(Byval Item) Dim scr Set scr = HMIRuntime.ScreenItems("MainPictureWindow") scr.Screen = "Detail_1.PDL" End Sub

Picture names are case-sensitive in WinCC V7 and TIA WinCC Professional; overview.pdl will not resolve to Overview.PDL. The same restriction applies to C code (see Section 5). If the picture must be loaded with a tag-prefix override (multi-language, multi-client), use the full path:

HMIRuntime.Trace = "::PROJECT::PlantA::Overview.PDL"

4.1 Why C Scripts Are Blocked in Menus

Menu definitions live in the Graphics Designer and are serialized as text into the project database *.PNL and *.MCP files. WinCC parses these files with a VBScript engine only; C source requires a separate compile step that the menu loader does not invoke. The behavior is unchanged from WinCC V6.2 through V8.0.

5. Reading and Writing Tags from C Script

The single most common source of "the C script generates errors" messages is a missing include and the wrong tag-name format. A minimal, correct C script that reads a process tag looks like this:

#include "apdefap.h" void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName) { double dValue; /* Always call the Get*Wait variant when the script runs from a button / menu because the asynchronous variant may return 0 on the first poll. */ dValue = GetTagDoubleWait("PlantA_Temperature"); if (dValue > 80.0) { SetTagDouble("PlantA_AlarmHigh", 1.0); } else { SetTagDouble("PlantA_AlarmHigh", 0.0); } }

5.1 Header and Type Rules

  • apdefap.h resolves all GetTag*, SetTag*, and DM_* prototypes. Skipping it produces the linker error "unresolved external symbol GetTagDouble".
  • Tag name is a plain string in C. Do not prefix with \ or :: — those prefixes are VBScript-only.
  • Match the data type: GetTagDouble for floats, GetTagWord for unsigned 16-bit, GetTagBit for booleans, GetTagChar for raw byte, GetTagString for text.

5.2 Internal vs External Tags

External (PLC) tags read through the configured channel driver without extra work. Internal tags (WinCC-only) require a WinCC variable to exist in the Tag Management; if the tag is missing, the call returns 0 (numeric) or an empty string and sets the system variable @SR_GetTagError to 1:

/* Best-practice read with error guard */ #include "apdefap.h" void ReadAndCheck(void) { DWORD dwErr; double v = GetTagDoubleWaitEx("PlantA_Temperature", &dwErr); if (dwErr != 0) { printf("Tag read failed, code %u\n", dwErr); return; } /* process v */ }

Common GetTagDoubleWaitEx error codes (hex):

Hex code Meaning Remediation
0x8004xxxx Tag not found in DM Add the tag in Tag Management; check spelling and case
0x8005xxxx Wrong data type Use the matching type-specific Get* call
0x8006xxxx Connection lost to PLC Check channel diagnostic, CP, network
0x8007xxxx Access denied (no authorization) Configure user level on the WinCC user

5.3 Address Syntax for Internal Tags

Internal tags behave like PLC tags from the C API. The address column in Tag Management is irrelevant for C; the WinCC-side name is what the script passes. To differentiate WinCC-side limits (e.g. 32.767 for 16-bit signed) the script must enforce them itself, or define a structure tag with a matching data type.

6. Common C Script Compilation and Runtime Errors

Symptom Root cause Fix
Unresolved external symbol GetTagDouble apdefap.h not included Add #include "apdefap.h" at the top
Function 'GetTagBit' not found Header search path missing Project → Properties → Include paths must contain applib and library
Script returns 0 but VBScript returns the real value Used GetTagDouble (async) before first poll Use GetTagDoubleWait on first call
Tag not found on a tag that exists in Tag Management Case mismatch; trailing space; project prefix missing Match the string exactly; check @PROJECT_PREFIX@
Compiler complains about lpszPictureName Wrong function signature for a button event Use the standard 3-arg signature shown in Section 5
Runtime: Stack overflow after script edit Infinite recursion between two C actions Audit call graph; introduce a guard tag
Script does nothing on a menu Menus reject C Move logic to VBScript, or to a button

7. C Script API Quick Reference

Operation C call Return / side effect
Read double, blocking double GetTagDoubleWait(const char*); Returns value; 0 on error
Read double, async double GetTagDouble(const char*); Returns 0 on first poll
Read with code double GetTagDoubleWaitEx(const char*, DWORD*); Sets *pdwError
Write double BOOL SetTagDouble(const char*, double); TRUE on success
Read bit / word BOOL GetTagBit, WORD GetTagWord Matches type
Read string (max 256) BOOL GetTagString(const char*, char*, DWORD); Copies into buffer
Open picture in window BOOL SSMOpenScreen(LPCTSTR pic, LPCTSTR screen, LPCTSTR window); From C only
Trigger screen change BOOL SSMChangeScreen(LPCTSTR pic, LPCTSTR screen, LPCTSTR window); Same
Stop Runtime BOOL DeactivateRT(void); Use sparingly, no confirm
Internal tag create / set DM_CREATE_VAR, DM_SET_VALUE For runtime-created tags

The full API surface is documented in WinCC V7.5 SP2 — ANSI-C for Creating Functions and Actions, manual entry ID 109973200 at the Siemens Industry Online Support portal.

8. Hybrid Strategies: C Inside VBScript Menus

When the logic must run in C (deterministic timing, complex math, OS-level calls) but the trigger is a menu, expose the C function as a project DLL and call it from VBScript via WinCC\_COM_ style wrappers or the newer HMIRuntime.Scripting bridge. The cleanest pattern is:

  1. Build a C DLL with a flat C ABI: __declspec(dllexport) void __cdecl ShutdownRT(void);
  2. Register the DLL in the project directory <Project>\library\.
  3. Declare it in VBScript: Declare Sub ShutdownRT Lib "MyProjectExt.dll" ()
  4. Call from the menu: Call ShutdownRT()
' Menu entry VBScript wrapper for a C DLL Declare Sub ShutdownRT Lib "MyProjectExt.dll" () Sub OnClick(Byval Item) If HMIRuntime.Authorization.Check("RT_Stop") = False Then Exit Sub Call ShutdownRT() End Sub

This pattern keeps the menu VBScript-only (legal) while still benefiting from C execution. It also avoids the legacy MScriptControl route, which is 32-bit only and unsupported on WinCC V8 x64 hosts.

9. Verification, Diagnostics, and Logging

After deploying a script, follow this checklist:

  1. Open WinCC Explorer → Tools → Status of Drivers and Connections; verify the tag in question is OK, not Disconnected.
  2. Add printf / sysprintf at strategic points; output is mirrored to the APDIAG directory in Diagnostics file WinCC_Sys_.log.
  3. For VBScript, set HMIRuntime.Trace = "MyTag='" & value & "'" and view in the diagnostic screen of the Graphics Designer.
  4. From the WinCC RT menu, Tools → Debug Scripts shows the last error code and the source line number when Project Properties → Options → Activate script debugger is enabled.
  5. Compile the C script with the Compile button on the C editor toolbar. Compile errors appear with a Click for details hyperlink that opens the apdiag.txt log.
WinCC stores the last 1,000 lines of script output in the file %ProgramData%\Siemens\Automation\WinCC\WinCC RT <N>\WinCC_Sys.log. Tail that file with PowerShell Get-Content -Wait during commissioning for live traces.

10. Version Notes and Migration

WinCC version C-API behavior VBScript behavior Notes
V7.0 / V7.0 SP3 Classic Get* / Set* HMIRuntime.Stop, Authorization Stop added in SP3
V7.3 Adds *WaitEx variants Adds TagSet collection Recommended baseline
V7.4 SP1 Async I/O for big tags Script debugger stabilized
V7.5 / V7.5 SP2 64-bit aware Improved object model Latest V7 branch
TIA WinCC Professional V16–V18 Different namespace Use HMIRuntime from V17+ Cross-load only via export
WinCC Unified (V17+) JavaScript replaces both No VBScript or C No migration of VBS/C as-is

For WinCC Unified (the Web-based successor), both C and VBScript are replaced by JavaScript; the menu restriction is moot because menus are now declarative widgets. The migration utility shipped with V17 (and refined in V18) rewrites simple VBScript into JS but cannot port the C actions — those must be re-implemented as user-defined functions in JS.

11. Practical Decision Flowchart

Use the flow below when you are unsure which language and which API to call:

Trigger source? Menu / Dynamic Dialog Button / Picture / Global Use VBScript only C or VBScript (engineer choice) Need C? Wrap in DLL and Declare in VBS For tag calls: include apdefap.h; use matching type

12. Field-Commissioning Notes

  • Numeric locale. In a German-locale project, the VBScript call CDbl("1,5") succeeds; the C call atof("1,5") returns 1.0 because C uses the C-locale. Always pass numeric values directly from the tag, not from text input.
  • Authority check. Always wrap HMIRuntime.Stop in HMIRuntime.Authorization.Check. Operators have been known to call the exit menu accidentally.
  • Redundancy. On a redundant WinCC pair, the menu-driven stop should also call HMIRuntime.Trace to log the user and timestamp; the partner server will take over and the local stop may otherwise be invisible to the audit trail.
  • Service-mode Runtime. When WinCC RT runs as a Windows service, CCStartStop.exe still works but the calling script must be elevated. The service wrapper logs return codes to WinCC_RT_Service.log.
  • Watchdog tags. Create a heartbeat tag (e.g. RT_Heartbeat) written by a 1-second cyclic C action. If the tag stops changing, the alarm system can flag a frozen Runtime even when the screen looks healthy.

Why does my menu click do nothing when I paste a C script there?

WinCC menus only accept VBScript. C scripts are silently rejected at parse time. Move the logic to a button, wrap the C in a DLL and call it via Declare Sub … Lib "…" from the menu's VBScript, or rewrite the logic in VBScript directly.

How do I stop WinCC Runtime from a custom menu entry?

Place HMIRuntime.Stop on the menu item's Mouse click event, ideally gated by an authorization check. For external callers use CCStartStop.exe /stop from the WinCC bin directory and run it under the same Windows account as the project.

Why does my C script get "unresolved external symbol GetTagDouble"?

The mandatory header apdefap.h is missing. Add #include "apdefap.h" at the top of the action. The header pulls in all GetTag*, SetTag*, and DM_* prototypes that the C compiler otherwise cannot resolve.

My C script returns 0 but VBScript returns the correct value. Why?

You are calling the asynchronous variant GetTagDouble on a script that runs before the first poll of the tag. Use GetTagDoubleWait or GetTagDoubleWaitEx for the first read so the script blocks until the driver has a value.

Can I use the same C code in WinCC V7 and TIA Portal WinCC Professional?

No. The C-API namespaces and project structures differ; the V7 APIs live in apdefap.h from the V7 install, while TIA WinCC Professional uses the SIMATIC Script runtime with a different API. Plan a rewrite when migrating to TIA WinCC, and a complete re-implementation in JavaScript for WinCC Unified (V17+).

Back to blog