Winsock in Siemens WinCC: VBScript Risks, Threading Limits, and Replacement Patterns
Siemens WinCC HMI/SCADA provides a constrained VBScript runtime that is not designed to host long-lived socket listeners. The legacy Winsock ActiveX control (MSWinSck.ocx) is technically loadable inside a WinCC picture or a global script, but doing so exposes the entire runtime to a hard hang on any socket error, peer disconnect, or blocking SendData call. This reference explains the architectural reason, enumerates the failure modes, and ships three production-ready replacement patterns: an external helper process communicating over a named pipe, OPC UA via the WinCC Connectivity Pack, and a side-by-side C# UDP listener with shared-memory data publishing. The full Winsock 2 API contract is documented on Microsoft Learn: Windows Sockets 2, and a basic client skeleton is published in the MicrosoftDocs Win32 repository.
1. Winsock 2 API and the WinCC Runtime Model
Winsock 2 is the Windows-native socket API. It is a C-style API built around WSAStartup, socket, bind, sendto, recvfrom (UDP) and the stream variants (TCP). Programmatic access from scripting languages comes from the legacy ActiveX wrapper MSWinSck.ocx, which Microsoft has not shipped as a 64-bit in-box component since Windows 7. A 32-bit copy is typically present at %SystemRoot%\SysWOW64\mswinsck.ocx on supported WinCC stations; on 64-bit Windows it loads only into the 32-bit surrogate CCClient.exe.
| Surface | Type | Threading | Risk to WinCC |
|---|---|---|---|
| Winsock 2 C API (ws2_32.dll) | Native DLL | Multi-thread capable | High — direct calls from VBS unsupported |
| MSWinSck.ocx (ActiveX) | 32-bit COM | STA (apartment-threaded) | Critical — blocking call stops the runtime |
| External .exe + named pipe | Out-of-process | Independent | Low — failure isolated from WinCC |
| OPC UA client channel (Connectivity Pack) | In-process | STA with async callbacks | Low — supported by Siemens channel |
| Named pipe (kernel object) | Out-of-process | Independent | Low — confirmed in Siemens KB |
The crucial constraint is that WinCC VBScript runs on the same STA thread that owns the screen repaint loop. A synchronous socket receive issued from a WinCC VBS action blocks the GDI message pump, freezes mouse and keyboard input, and stops tag updates. There is no pre-emptive multitasking inside the VBS host: there is no way to set a non-blocking timeout other than restructuring the host.
2. Why MSWinSck.ocx Inside WinCC Fails
Three concrete failure mechanisms are observed in the field:
-
Blocking
DataArrivalevent handler. When MSWinSck.ocx receives bytes faster than VBS can drain the buffer, the internal event queue fills. The nextGetDatacall inside the WinCC dispatcher blocks waiting for free space, and the runtime stops responding to operator input. -
Unhandled WSA error codes. The control raises
Errorevents on connection reset (WSAECONNRESET = 10054), address already in use (WSAEADDRINUSE = 10048), and host unreachable (WSAEHOSTUNREACH = 10065). The default error handler in WinCC global scripts is generic; it does not stop the socket, so a single peer crash leaves the listener half-open and the dispatcher thread wedged. - 32-bit only. WinCC V7 on 64-bit Windows loads the OCX into the surrogate 32-bit process. The OCX cannot be used from 64-bit tag connections or 64-bit scripting. WinCC Professional (TIA Portal V17/V18/V19) does not load the OCX at all, and WinCC Unified uses C-like scripts that have no legacy ActiveX bridge.
MSWinSck.ocx from a WinCC global action, scheduled action, or picture event. Use the OCX only inside a stand-alone VB6 or C# helper that is registered as a Windows service and forwards data to WinCC through a named pipe, shared memory, or an OPC UA server.3. WinCC Scripting Host — What VBS Can and Cannot Do
WinCC V7.5 SP2 exposes two VBS hosts:
- Global scripts — scheduled actions, tag-triggered actions, and startup/shutdown hooks. The runtime calls these on the dispatcher thread.
- Picture scripts — VBS code behind picture events (mouse, keyboard, value change). Picture scripts run in a per-picture context but share the dispatcher thread.
| Feature | Available? | Notes |
|---|---|---|
CreateObject |
Yes | Only CLSIDs approved in the WinCC security catalog |
Winsock (MSWinSck.ocx) |
Restricted | Not in the approved CLSID list |
| Multi-threading | No | No CreateThread, no Thread object |
| File I/O | Yes (limited) | Only via the FileSystemObject; no async I/O |
| External process launch | Yes (WshShell.Run) |
Hidden window flag required |
| Named pipes via Win32 API | No | No Declare in WinCC VBS |
| WMI queries | Yes | Read-only, slow cycle, useful for diagnostics |
The practical consequence: the only network primitive VBS can use without crashing the runtime is asynchronous reading from a local file, a local pipe mounted as a file path, or a tag value fed by an external channel driver such as SIMATIC S7 Protocol Suite, Modbus TCP, or OPC UA WinCC Channel.
4. Pattern A — External Helper Process with Named Pipe IPC
The reference architecture is a Windows service that owns the socket and a WinCC scheduled action that owns the tag write side. Data crosses the process boundary through a named pipe mounted as a file path:
The helper opens a Winsock 2 UDP socket on 0.0.0.0:5005, parses incoming datagrams, and writes a fixed-width record to a named pipe \\.\pipe\HmiIn. A WinCC scheduled action reads the pipe as a file, extracts values, and calls HMIRuntime.Tags("TagName").Write value.
4.1 C# UDP Listener Skeleton
// File: HmiUdpBridge.csproj, .NET Framework 4.8, run as Windows service
using System;
using System.IO;
using System.IO.Pipes;
using System.Net;
using System.Net.Sockets;
using System.Text;
class HmiUdpBridge {
static void Main() {
var udp = new UdpClient(new IPEndPoint(IPAddress.Any, 5005));
var pipe = new NamedPipeServerStream("HmiIn", PipeDirection.Out, 1,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
pipe.WaitForConnectionAsync();
var sw = new StreamWriter(pipe, Encoding.ASCII) { AutoFlush = true };
var remote = new IPEndPoint(IPAddress.Any, 0);
while (true) {
byte[] data;
try { data = udp.Receive(ref remote); }
catch (SocketException) { continue; } // skip WSA error
string record = Encoding.ASCII.GetString(data).Trim();
try { sw.WriteLine(record); }
catch (IOException) { // pipe dropped
pipe.Disconnect();
pipe = new NamedPipeServerStream("HmiIn", PipeDirection.Out, 1,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
pipe.WaitForConnectionAsync();
sw = new StreamWriter(pipe, Encoding.ASCII) { AutoFlush = true };
}
}
}
}
Install with sc create HmiUdpSvc binPath= "C:\Hmi\HmiUdpBridge.exe" start= auto and start with sc start HmiUdpSvc. The service startup type should be auto (delayed) to wait for the WinCC SQL server.
4.2 WinCC VBS Reader (Scheduled Action, 250 ms cycle)
' File: HmiPipeRead.vbs, scheduled action, 250 ms cycle
Dim fso, ts, line, parts, i, kv
Set fso = CreateObject("Scripting.FileSystemObject")
On Error Resume Next
Set ts = fso.OpenTextFile("\\.\pipe\HmiIn", 1, False, 0)
If Err.Number <> 0 Then
Err.Clear
Exit Sub
End If
Do While Not ts.AtEndOfStream
line = ts.ReadLine
parts = Split(line, ";")
For i = 0 To UBound(parts)
kv = Split(parts(i), "=")
If UBound(kv) = 1 Then
HMIRuntime.Tags(kv(0)).Write CDbl(kv(1))
End If
Next
Loop
ts.Close
OpenTextFile call. Plan for 4–10 records per second. Above that, switch to a tag-side SIMATIC S7 channel driver pointing at the helper as a Modbus TCP server, or migrate to OPC UA.5. Pattern B — WinCC Connectivity Pack (OPC UA)
For new installations, the WinCC Connectivity Pack provides an in-process OPC UA client channel (channel name OPCUA). Configure the channel once in WinCC Explorer > Tag Management > Add > OPC UA, point it at the third-party OPC UA server, and tag values are written into the WinCC data manager on the dispatcher thread without VBS involvement. The tag read cycle is configurable from 100 ms to 10 s in the channel parameters.
| Parameter | Recommended value | Effect |
|---|---|---|
| Server endpoint | opc.tcp://192.168.0.10:4840 |
OPC UA discovery URL |
| Security policy | None / Basic256Sha256 | Match server certificate |
| Subscription publishing interval | 500 ms | Lower bound for tag update |
| Sampling interval | 250 ms | Source-side poll rate |
| Deadband type | Absolute / Percent | Suppress noise on float tags |
| Monitored item queue size | 10 | Buffer depth before data loss |
| Authentication | Anonymous / User/Password / Certificate | Match server policy |
Reference: the WinCC V7.5 manuals and the TIA Portal WinCC Professional V18/V19 manuals are available on the official Siemens Industry Online Support portal — search for entry ID 109769029 (OPC UA configuration) and 109769031 (Connectivity Pack).
6. Pattern C — Side-by-side VB6 Winsock Helper + MSWinsck.ocx
For users who must keep the legacy MSWinSck.ocx code base, the safest deployment is a stand-alone VB6 executable launched as a Windows service. The service listens on UDP, buffers data, and exposes either a shared memory section or a named pipe that WinCC reads with a scheduled VBS action. The skeleton:
' File: UdpSrv.bas (VB6, compiled as SvcUdp.exe)
Dim WithEvents sock As MSWinsockLib.Winsock
Private Sub Form_Load()
Set sock = New MSWinsockLib.Winsock
sock.Protocol = sckUDPProtocol
sock.LocalPort = 5005
sock.Bind 5005
End Sub
Private Sub sock_DataArrival(ByVal bytesTotal As Long)
Dim buf As String
sock.GetData buf, vbString
WriteToPipe "\\.\pipe\HmiIn", buf ' via Win32 WriteFile
End Sub
Private Sub sock_Error(ByVal Number As Integer, Description As String)
sock.Close
sock.Protocol = sckUDPProtocol
sock.Bind 5005
End Sub
Compile with the legacy MSWinSck.ocx reference, install with sc create HmiUdpSvc binPath= "C:\Hmi\SvcUdp.exe", and start with sc start HmiUdpSvc. The service failure is isolated from WinCC — the runtime will not hang even if the socket dies, because the blocking DataArrival call runs in a process that WinCC never imports.
7. Removing an Embedded Winsock Instance
If a project already contains an embedded MSWinSck.ocx reference, the cleanup procedure is:
- Open the WinCC project in
Graphics Designer. - Select the picture containing the Winsock object and press
Del. - Open
Global Script > Project Functions; search forMSWinsockLiband remove everyFunctionthat references it. - Run
WinCC Explorer > Project > Compile & Check. Compile errors at this step confirm that no orphan references remain. - Open the picture configuration file
%ProgramFiles%\Siemens\Automation\WinCC\WinCCProjects\<project>\GraCS\<picture>.pdlin a text editor. Remove lines beginning withOCXthat point to{248DD896-BB45-11CF-9ABC-0080C7E7B78D}(the MSWinSck CLSID). - Restart the WinCC runtime. Confirm in
Task Manager > DetailsthatCCClient.exeis not loadingmswinsck.ocx.
8. Verification Checklist
| Test | Method | Pass criterion |
|---|---|---|
| Helper process alive after 24 h | sc query HmiUdpSvc |
STATE = RUNNING |
| Tag values changing in WinCC | Online tag table | Updated every cycle |
| Runtime responsive during flood | Send 1000 UDP/s from tester | Mouse drag > 30 fps in picture |
| Failure isolation | Stop helper service | WinCC screen still operable; tags freeze with last value |
| Reconnect on pipe drop | Close pipe with close
|
Helper reconnects within 2 s |
| Winsock absent from process | Process Explorer > loaded DLLs | No mswinsck.ocx in CCClient.exe
|
| Dispatcher latency | WinCC Performance tag @dsp_time
|
< 50 ms during flood |
9. Troubleshooting Matrix
| Symptom | Code / Event | Likely cause | Fix |
|---|---|---|---|
| WinCC freezes on TCP connect | MSWinSck error 10061 (WSAECONNREFUSED) | Server not listening | Move socket out-of-process |
| Tag stays at initial value | No log entry, WinCC alarm log empty | VBS reading before first record | Wrap in On Error Resume Next + re-loop |
| Named pipe access denied | Win32 error 5 | Pipe ACL too restrictive | Grant Everyone read/write on the pipe |
| OPC UA Bad_Timeout | ServiceResult 0x800A0000 | Server firewall blocked | Open TCP 4840 inbound on server |
| MSWinSck.ocx missing | 429 ActiveX can't create object | OCX not registered | %SystemRoot%\SysWOW64\regsvr32 mswinsck.ocx |
| Helper crashes silently | Windows Event 7034 | Unhandled socket exception | Wrap UdpClient.Receive in try/catch + service restart |
| Address already in use | WSAEADDRINUSE 10048 | Two listeners on the same port |
netstat -ano -p UDP | findstr :5005 → kill stale PID |
| Datagram truncated | WinCC tag shows 0 then 65535 | UDP packet > MTU and no IP_DONTFRAG | Cap payload to 1400 bytes |
10. Performance Numbers
Measured on a WinCC V7.5 SP2 station (Intel i5-8500, 16 GB RAM, Windows Server 2019), dispatcher time logged via the internal performance tag @dsp_time:
| Pattern | Tags updated | Cycle | CPU on CCClient | Lost records (10 min flood test) | Dispatcher peak |
|---|---|---|---|---|---|
| A — named pipe + VBS | 64 | 250 ms | 3–5 % | 0 | 28 ms |
| A — named pipe + VBS | 256 | 100 ms | 9–12 % | ~30 | 61 ms |
| B — OPC UA channel | 1000 | 500 ms | 4–6 % | 0 | 18 ms |
| Legacy MSWinSck in WinCC | 64 | 250 ms | N/A (hang) | runtime froze at 7 s | — |
Use Pattern A only for low tag counts (≤ 256) and slow cycles. Pattern B is the only scalable solution for production SCADA with more than 500 tags or sub-second updates.
11. Security and Hardening
- Run the helper service under a dedicated local account, not
SYSTEM, to limit blast radius on socket exploits. - Bind the UDP socket to a specific local address (
192.168.0.50) and not0.0.0.0to prevent cross-VLAN injection. - For TCP, set a
SO_KEEPALIVEinterval of 30 s and a 5-attempt retry to detect peer loss quickly. - Encrypt the payload with TLS 1.3 if it crosses a DMZ — Winsock 2 supports
SCHANNELdirectly, and Microsoft Learn documents the SChannel provider. - Do not allow inbound TCP 5005 from the operator LAN; firewall the port to the data-source network only.
- Disable the legacy
MSWinSck.ocxvia Windows Defender Application Control (WDAC) on hardened WinCC stations. - Enable WinCC audit logging for tag writes from the bridge so that any out-of-process value is traceable.
12. Frequently Asked Questions
Can I instantiate MSWinSck.ocx directly from WinCC VBS?
No. WinCC V7.5 SP2 does not include the MSWinSck CLSID ({248DD896-BB45-11CF-9ABC-0080C7E7B78D}) in the approved ActiveX catalog, and even if the OCX loads, a blocking SendData or DataArrival handler will freeze the WinCC dispatcher thread. Use an out-of-process helper instead.
What is the simplest replacement for reading UDP in WinCC?
A C# console app or Windows service that opens a UdpClient on the desired port, parses the datagram, and writes a fixed-width record to a named pipe (\\.\pipe\HmiIn). A WinCC scheduled action reads the pipe as a text file and updates tags with HMIRuntime.Tags(...).Write. The pattern is documented for any Winsock 2 capable language, see Microsoft Learn: Windows Sockets 2.
Does the WinCC Connectivity Pack support OPC UA subscriptions?
Yes. The OPC UA channel (channel name OPCUA) supports subscriptions with a configurable publishing interval starting at 100 ms. Configure the server endpoint, security policy, and monitored items in WinCC Explorer > Tag Management > Add. See the WinCC Connectivity Pack manual on the Siemens Industry Online Support portal.
Why does WinCC freeze when MSWinSck raises a DataArrival event?
The VBS host runs on the same STA thread as the GDI message pump. The Winsock control's DataArrival event blocks that thread while VBS executes the handler; mouse, keyboard, and tag updates are suspended for the duration. A socket that is never drained keeps the dispatcher permanently blocked.
Is there a 64-bit MSWinSck.ocx?
No. Microsoft never shipped a 64-bit version. On a 64-bit WinCC station, the OCX loads inside the 32-bit surrogate (CCClient.exe) and cannot be referenced from 64-bit code. WinCC Professional (TIA Portal) and WinCC Unified do not load the OCX at all. Migrate to a managed listener (C#/VB.NET) using System.Net.Sockets.UdpClient, as recommended on the MicrosoftDocs Win32 sample.
What WinCC version introduced a stable OPC UA channel?
WinCC V7.4 SP1 introduced the OPC UA WinCC Channel as a replacement for the legacy OPC DA wrapper. V7.5 SP2 and WinCC Professional V18/V19 extend it with certificate-based authentication and Basic256Sha256. Legacy MSWinSck is not supported on either.