1. Problem Statement: WinCC Crashes Under Forced Read/Write Load
Siemens SIMATIC WinCC (both the classic V7.x and the TIA Portal WinCC Unified V16-V20 runtime) can lose responsiveness, drop tag updates, and ultimately crash the runtime process when an external OEM controller (PLC, robot controller, vision system, or third-party device) is switched off, powered down, or loses its network interface while the HMI/SCADA layer is still actively polling it. The failure mode is amplified dramatically when forced (asynchronous) read and write operations are issued from C-scripts, VBScript actions, or Global Script routines. Each forced call spawns an individual communication telegram outside of the standard acquisition cycle, so a long-running script that loops over many tags and writes them one at a time can saturate the channel driver long before the configured acquisition cycle would ever overflow.
When the OEM device is unreachable, the request queue grows monotonically: the driver sends the request, the OS times out at the TCP or MPI/PROFIBUS layer, the retry counter is incremented, and the request remains in the queue. After the queue's depth threshold is exceeded, the channel DLL either returns escalating error codes, drops new requests silently, or, in worst-case scenarios, asserts and terminates the WinCC Explorer / RT process tree. Operators see this as the HMI freezing, alarm logging stalling, and the classic "WinCC has stopped working" dialog.
2. Root Cause Analysis: Why Forced Read/Write Overloads the Channel
WinCC communicates with automation devices through channel DLLs (e.g., S7DOS for S7 PLCs, SIMATIC S7 Protocol Suite for TCP/IP, MPI, PROFIBUS DP, or Allen-Bradley DF1 for third-party OEMs). Each channel maintains an internal request queue and a response queue. The acquisition cycle (configured under Tag Management → Properties → Update) polls tags at a deterministic interval, and the driver naturally rate-limits itself. Forced read/write commands bypass this throttle.
2.1 Synchronous vs. Asynchronous (Forced) Access
| Attribute | Synchronous (Cyclic) | Asynchronous (Forced) |
|---|---|---|
| Trigger | Acquisition cycle timer (e.g., 1 s, 500 ms) | Script command issued immediately |
| Queuing | Coalesced into the next cycle | Each call is a separate telegram |
| Backpressure | Natural (next cycle waits) | None - direct injection into TX queue |
| C API | GetTagXXX / SetTagXXX (no Wait) | GetTagXXXWait / SetTagXXXWait |
| VBScript API | HMIRuntime.Tags(...).Read / .Write | Same, with Wait:=True or 1 flag |
| Risk on link loss | Low (one tag per cycle, retry handled) | High (thousands of stacked requests) |
2.2 The Physics of the Overflow
When the OEM link is down, the channel's TX socket returns either WSAETIMEDOUT (TCP retransmit timeout) or ERROR_TIMEOUT at the Win32 layer. WinCC's retry logic appends the request back to the head of the queue rather than dropping it, because the application semantics demand that a write be acknowledged. The queue depth N therefore grows approximately as:
N(t) = N₀ + R(t) · τ
where R(t) is the forced request rate (requests per second issued by the script), and τ is the average time the request spends in the queue waiting for an answer that will never come. On a saturated Ethernet link with the OEM unreachable, τ is dominated by the TCP retransmit timeout (typically 3-21 s depending on the OS) plus the WinCC internal retry counter (default 3 attempts). A script that issues 100 forced writes per second therefore adds 100 · 21 s = 2,100 pending requests in the worst case. Most channel DLLs cap the queue at 2,048-4,096 entries before the driver asserts.
3. WinCC Communication Architecture Reference
Understanding the architecture is essential for diagnosis. The classical WinCC V7 data path is:
-
Tag Management — defines the symbolic tag name, address (e.g.,
DB100.DBW0), data type, and update cycle. - Channel DLL — packages the tag request into a vendor-specific telegram (S7 comm, Modbus TCP, OPC, etc.).
- Connection unit — opens and maintains the physical/logical connection (e.g., TCP socket on port 102 for S7).
- Device driver — handles the link layer (MPI/PROFIBUS/TCP).
- Tag image (process image) — the in-memory copy of all tag values used by the HMI screens.
- Scripting engine — C and VBS actions read/write the process image, and (if forced) generate additional channel requests.
For WinCC Unified (V16-V20), the architecture is rebuilt on the WinCC Unified Runtime, which uses the SIMATIC Runtime Manager and the RT Unified channel subsystem. The command-line interface of the SIMATIC Runtime Manager (see Operation via command line - WinCC Unified) provides a way to query channel state and to gracefully shut down runtime if a controller disappears.
4. Diagnosing the Overflow: Status of Driver Connections
The built-in diagnostic tool is the single most important weapon against this failure. Open WinCC Explorer → Tools → Status of Driver Connections. The dialog exposes four critical counters per logical connection:
| Column | Meaning | Healthy Value | Overflow Signature |
|---|---|---|---|
| Tag read | Cumulative tags read since runtime start | Monotonically increasing | Stops or stalls |
| Tag written | Cumulative tags written since runtime start | Monotonically increasing | Stops or stalls |
| Read requests | Pending (queued) read requests | 0 or 1 | Steadily climbing, > 50 |
| Write requests | Pending (queued) write requests | 0 or 1 | Steadily climbing, > 50 |
| Connection state | Logical link status | Established / OK | Disconnected, Fault |
If the "Read requests" or "Write requests" counters increase continuously while the connection state is anything other than "OK", the channel is overloaded. In this condition, take immediate corrective action (see Section 7) before runtime becomes unstable.
4.1 Programmatic Access to Connection State
In a production environment, you cannot rely on an operator opening the dialog. Use the WinCC OLE/DCOM or the WinCC Unified REST/GraphQL API to surface the same counters in the alarm log. Example for classic WinCC using the DM (Data Manager) OLE interface:
Set objConn = CreateObject("WinCC-Runtime-ActiveXDll.Connection")
strState = objConn.GetState("S7-Connection_1")
lngPendingReads = objConn.GetPendingReadRequests("S7-Connection_1")
If lngPendingReads > 100 Then
HMIRuntime.Trace "OVERLOAD: " & lngPendingReads & " pending reads\n"
End If
For WinCC Unified, the same data is reachable via the Connections node of the Unified tag interface and the Logs service.
5. Scripting Discipline: Eliminating the Forced Flood
The most common code-smell in WinCC scripts is the "loop-and-force" pattern. The following anti-pattern appears in roughly 40% of brownfield sites audited by Siemens service:
' ANTI-PATTERN - DO NOT USE
For i = 0 To 499
HMIRuntime.Tags("OEM_DB_" & i & ".DW0").Write 0, 1 ' 1 = async/forced
Next i
This generates 500 separate telegrams in a few milliseconds, with no backpressure. Replace it with one of the following idiomatic patterns.
5.1 Use Synchronous (Cyclic) Writes for Bulk Operations
If the values can be set once and refreshed by the acquisition cycle, drop the 1 flag and let the channel batch the writes:
' CORRECT - synchronous, coalesced
For i = 0 To 499
HMIRuntime.Tags("OEM_DB_" & i & ".DW0").Write 0 ' no Wait flag
Next i
The channel will pack these into the next acquisition cycle, often reducing 500 telegrams to 1-2 PDUs.
5.2 Use SetTagXXXWait in C-Actions Only When an Acknowledgment Is Required
Forces make sense when the script must verify that the OEM accepted the value before continuing. In that case, restrict the loop and verify the return code:
DWORD dwRet;
for (int i = 0; i < 10; i++) {
dwRet = SetTagWordWait("OEM_Cmd", (WORD)i, &dwValue);
if (dwRet != 0) {
printf("OEM write failed, code %u, aborting loop\n", dwRet);
break; // stop flooding on first error
}
Sleep(50); // pacing, 20 writes/s maximum
}
The Sleep(50) is critical: it caps the request rate to 20/s, which keeps the queue shallow even on a dead link (20/s · 21 s = 420 pending, well under the cap).
5.3 Use VBScript Optional Parameter Correctly
The signature is Write value [, Wait] [, ErrorSource] [, UserName]. The integer 1 enables forced (async) mode. Use 0 (or omit) for synchronous mode:
HMIRuntime.Tags("OEM_Cmd").Write 0, 0 ' synchronous
HMIRuntime.Tags("OEM_Cmd").Write 0, 1 ' asynchronous (forced)
6. Connection Supervision: Detecting OEM-OFFLINE
Do not let a script keep hammering a dead link. Add a global connection-watchdog that monitors the channel state and disables forced traffic when the OEM drops. The classic approach uses a periodic check on a "heartbeat" tag that the OEM must refresh every second.
' Global Script, triggered every 1 s
Dim tHeartbeat, bOEMAlive
tHeartbeat = HMIRuntime.Tags("OEM_Heartbeat").Read
bOEMAlive = (DateDiff("s", tHeartbeat, Now) < 5)
HMIRuntime.Tags("OEM_Alive_Flag").Write bOEMAlive, 0 ' synchronous
' In any forced-write script, guard with the flag:
If HMIRuntime.Tags("OEM_Alive_Flag").Read Then
HMIRuntime.Tags("OEM_Cmd").Write 0, 1
Else
HMIRuntime.Trace "OEM offline, skipping forced write\n"
End If
For WinCC Unified, replace the global script with a scheduled Global Script job or a Unified Logging rule that disables the connection on heartbeat timeout.
7. Mitigation Strategies Summary
| Strategy | Where Applied | Effect on Queue Depth |
|---|---|---|
| Replace forced with cyclic writes | All bulk write scripts | Reduces by 100-1000x |
| Add Sleep / pacing in loops | C and VBS forced loops | Bounds rate to < 20/s |
| Guard with heartbeat check | Every forced script | Zero traffic on dead link |
| Increase channel timeout | Channel configuration | Fewer false retries (use sparingly) |
| Reduce retry count | Channel configuration (default 3) | Drops dead requests faster |
| Stop WinCC Runtime when OEM is OFF | Operational SOP | Eliminates the issue entirely |
| Use SIMATIC Runtime Manager CLI | WinCC Unified V16-V20 | Programmatic shutdown on fault |
7.1 Operational Best Practice: Stop Runtime When OEM Is Off
The simplest and most reliable mitigation is to stop the WinCC Runtime whenever the OEM controller is not running. This is the recommendation issued by Siemens support for shop-floor cells where the OEM is a third-party machine that is regularly powered down for maintenance. In WinCC V7, stop the runtime from the project manager; in WinCC Unified, issue a graceful shutdown through the SIMATIC Runtime Manager command-line interface (see Operation via command line - WinCC Unified).
8. WinCC Unified-Specific Considerations (V16-V20)
WinCC Unified uses a different channel driver stack (RT Unified) and the SIMATIC Runtime Manager. Key differences relevant to the buffer-overflow issue:
-
Tag handling: Unified tags are bound at compile time; the run-time uses the HMI tag table in the device configuration. A forced read in Unified is issued via the JavaScript API
Tags("name").Read()with the optionalasyncargument. -
Channel supervision: Unified exposes the
ConnectionStateproperty of each connection in the tag interface. Subscribe to theConnectionStateChangedevent in a global script to react within one acquisition cycle of a link drop. -
Runtime Manager: The SIMATIC Runtime Manager command-line interface (see reference above) can be used in a service routine to start, stop, or restart the runtime, and to query connection states via
RTMgr.exe /status. -
Logging: Unified's
Logsservice records every forced read/write with timestamp, tag name, and result code. Inspect these logs to identify scripts that are spamming the channel.
9. Verification Procedure
After applying the mitigations, validate with the following acceptance test:
- Start WinCC Runtime with the OEM online and the heartbeat running.
- Confirm the Status of Driver Connections dialog shows "Read requests" = 0 and "Write requests" = 0 for all OEM connections.
- Force the OEM offline (power off or pull the network cable). Confirm the connection state transitions to "Disconnected" within one heartbeat interval (5 s).
- Watch the Read requests and Write requests counters for 10 minutes. They must remain at or below 1.
- Run a representative script that previously caused the crash. Confirm it either skips the forced write (via the heartbeat guard) or terminates early on the first error.
- Confirm the runtime is stable for 30 minutes with the OEM offline. No crash, no freeze, no orphan processes.
- Bring the OEM back online. Confirm the channel re-establishes automatically and the counters resume normal behaviour.
10. Troubleshooting Matrix
| Symptom | Likely Cause | Diagnostic Step | Fix |
|---|---|---|---|
| HMI freezes 1-5 min after OEM OFF | Forced write loop flooding queue | Status of Driver Connections → Write requests climbing | Convert to cyclic or add Sleep/heartbeat guard |
| Alarm log stops logging | Channel DLL assert | Windows Event Viewer → Application log for WinCC error | Reduce forced traffic, restart runtime |
| Scripts run slowly without crash | Queue depth high, delayed acks | Status of Driver Connections → Read requests > 10 | Reduce acquisition rate, eliminate forced calls |
| Runtime crashes on startup with OEM OFF | Startup script issues forced write before link init | Enable WinCC trace, look for forced calls in Startup event |
Defer forced calls to first valid heartbeat |
| Connection state OK but tags stale | Channel retry counter exhausted, no error raised | Compare Tag read counter with expected rate | Lower retry count, increase timeout |
| Unified Runtime loses connections but WinCC V7 does not | Different channel DLL behaviour | Compare channel parameter sets | Align retry and timeout settings across projects |
What is the difference between a forced read/write and a cyclic read/write in WinCC?
A cyclic read/write happens on a scheduled acquisition cycle (e.g., every 1 s) and is naturally rate-limited by the channel. A forced (asynchronous) read/write is issued immediately from a script via GetTagXXXWait / SetTagXXXWait in C, or the optional 1 parameter in VBScript HMIRuntime.Tags(...).Write value, 1. Each forced call generates a separate telegram outside the cycle and has no backpressure, which is why heavy use can overflow the channel queue when the target device is offline.
How do I detect a WinCC buffer overflow in real time?
Open WinCC Explorer → Tools → Status of Driver Connections. Monitor the Read requests and Write requests columns. Healthy values are 0 or 1; a steady increase above 50 means the channel is overloaded and a crash is imminent. In production, surface these counters via the OLE interface or the WinCC Unified tag API to a global alarm that triggers when the threshold is exceeded.
Can forced read/write really crash WinCC?
Yes. When the OEM controller is offline, each forced call retries internally and stays queued. A script that issues 100 forced writes per second can queue thousands of requests within one TCP retransmit timeout window (3-21 s). When the channel DLL's internal queue cap (typically 2,048-4,096 entries) is exceeded, the driver asserts and the WinCC runtime process terminates. The crash usually occurs 30 s to 5 minutes after the OEM is powered off, not immediately.
Should I stop WinCC Runtime when the OEM is off?
Yes — that is the cleanest mitigation. In WinCC V7, stop the runtime from the project manager. In WinCC Unified V16-V20, you can script a graceful shutdown through the SIMATIC Runtime Manager command-line interface (see Operation via command line - WinCC Unified). If you cannot stop the runtime (e.g., other cells depend on it), at minimum add a heartbeat guard to every forced script so it skips writes when the OEM is unreachable.
How do I pace a forced write loop to avoid overflow?
Insert a Sleep(50) (50 ms) in C, or a VBScript WScript.Sleep 50 equivalent, between iterations. This caps the forced-write rate at 20 per second. Combined with the TCP retransmit timeout of 21 s, the steady-state queue depth is bounded at 420, well below the channel cap. Also check the return code of every forced call and break out of the loop on the first error so a dead link does not get a full retry storm.