Reading Serial Barcode Data into WinCC Runtime via MSComm32.ocx

David Krause12 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

Overview: WinCC Runtime Serial Port Integration

WinCC Runtime Professional and WinCC V7.x do not expose a native serial I/O driver for ASCII/RS232 devices on the engineering station or the OS client. To read data from a barcode scanner, scale, GPS, or any RS232 endpoint without a CP340/CP341 hardware module, the standard field-proven path is to embed the Microsoft MSComm32.ocx ActiveX control inside a WinCC picture, drive it with VBScript (preferred) or a C action, and route the received bytes into a WinCC internal tag. The ActiveX speaks directly to the Win32 COMM API (\Device\Serial0..n), bypassing the need for a SIMATIC S7 CP module or an OPC server wrapper.

This guide focuses on the documented pattern Siemens publishes in the WinCC Knowledge Base: Entry ID 28378296 - How can you send or receive data via the serial interface in WinCC Runtime?. The pattern works on WinCC V7.0 SP3 through V7.5 SP2 on Windows 7 SP1 / Windows 10 LTSC / Windows Server 2012 R2 / 2019. It is not supported on WinCC Unified (V16+), which has its own SysSerial namespace and does not require an OCX.

Third-party ActiveX disclaimer: Siemens explicitly states that no liability is assumed and no guarantee is granted for the use of mscomm32.ocx. Treat it as a legacy COM component and lock down the engineering station accordingly. On 64-bit Windows you must register the 32-bit OCX because WinCC Runtime is a 32-bit process.

Prerequisites and Architecture

Before configuring the picture, verify the following hardware and software prerequisites.

Item Requirement Notes
WinCC version V7.0 SP3 or later, RT or RT + ES on same node Tested against V7.1, V7.2, V7.3, V7.4 SP1, V7.5 SP2
OS Windows 7 SP1 / 10 LTSC 2019 / Server 2012 R2 / 2019 (32- or 64-bit) 64-bit hosts must run 32-bit registration
MSComm32.ocx Version 6.1.98.16 (mscomm32.ocx) shipped with VB6 SP6 runtime Redistributable, ~104 KB
Physical COM port Native RS232 DB-9, USB-to-RS232 (FTDI FT232, Prolific PL2303), or PCI multi-port card Appears as COM1..COMn in Device Manager
Barcode scanner RS232 output, ASCII framing, terminator CR (0x0D) or CR+LF (0x0D 0x0A) Most industrial scanners default to 9600-8-N-1
User rights Local administrator for OCX registration, then standard user for Runtime Lock down after install

The runtime data flow is:

  1. Scanner emits ASCII frame terminated by CR/LF on the physical COM1.
  2. The MSComm32 ActiveX control inside the WinCC picture raises an OnComm event when bytes are buffered.
  3. A VBScript handler reads the Input property, strips the terminator, validates the payload, and writes the cleaned string to a WinCC internal tag (e.g., Barcode_Last).
  4. A WinCC timer (or scheduled VBS action) triggers scans every 5 minutes by pulsing the scanner's trigger line through MSComm.CommPort RTS/DTR, or simply by waiting on the next autonomous scan.
  5. Optional: a tag logging frame persists the value to a circular archive at TagLoggingSlow.

Installing and Registering MSComm32.ocx

On a 64-bit Windows host, the WinCC Runtime process is 32-bit. The OCX must therefore be registered in the WOW6432 node.

  1. Copy mscomm32.ocx to %SystemRoot%\SysWOW64\ (64-bit OS) or %SystemRoot%\System32\ (32-bit OS).
  2. Open an elevated command prompt.
  3. Register the 32-bit OCX:
    cd C:\Windows\SysWOW64
    regsvr32.exe mscomm32.ocx
  4. Expected dialog: DllRegisterServer in mscomm32.ocx succeeded.
  5. Verify the COM registration:
    reg query "HKCR\CLSID\{648A5600-2C6E-101B-82B6-0000C0BBA6B5}"
Anti-virus impact: Several endpoint protection suites (CrowdStrike, Trend Micro, Defender ATP) block unsigned OCX registration or strip the registry keys during scans. Add mscomm32.ocx to the AV exclusion list before running regsvr32, otherwise the ActiveX will appear in the WinCC insert dialog but fail to instantiate with error 0x80040112 (CLASS_E_CLASSNOTREG).

Configuring the COM Port Parameters

Match the serial parameters on the scanner to the values written into the MSComm control. The defaults below cover 95% of industrial 1D/2D imagers.

Property Typical value Description
CommPort 1 COM1. For USB-to-serial use Device Manager to map a stable COM number (e.g., COM4).
Settings "9600,N,8,1" 9600 bps, no parity, 8 data bits, 1 stop bit
Handshaking comNone (0) or comRTSXOnXOff (3) comNone = no flow control. Use RTS/CTS for noisy panels.
InputMode comInputModeText (0) Returns VB string. Use comInputModeBinary (1) for non-ASCII.
RThreshold 1 Fire OnComm after every byte. Use N for fixed frame length scanners.
SThreshold 0 Disable transmit buffer events
InputLen 0 Read whole buffer. Set 13 if scanner emits fixed 13-char code39.
PortOpen True Open the port. Closing the picture should close it.

Adding MSComm to the WinCC Graphics Designer

  1. Open Graphics Designer and load the target picture (e.g., Start.pdl).
  2. Right-click the empty area, choose Smart Objects > ActiveX Control, or use the toolbar Insert > ActiveX Control.
  3. In the Insert ActiveX Control dialog, scroll to Microsoft Communications Control, version 6.0. If absent, the OCX is not registered correctly.
  4. Place the control. Rename the object to MSComm1 via the Properties pane (Object Name field).
  5. Set the initial properties on the Properties tab:
    MSComm1.CommPort  = 1
    MSComm1.Settings  = "9600,N,8,1"
    MSComm1.Handshaking = 0       'comNone
    MSComm1.InputMode  = 0        'comInputModeText
    MSComm1.RThreshold = 1
    MSComm1.PortOpen   = True
  6. Set Visible to No if the control is purely a data conduit and should not appear in Runtime.

VBScript Implementation for Barcode Reading

Create the internal tags first in the WinCC Tag Management. Right-click Internal Tags > New and create the following.

Tag name Data type Length Purpose
Barcode_Last Text tag, 8-bit char set 32 Last accepted scan
Barcode_Count Unsigned 32-bit - Monotonic counter for sequence
Barcode_Status Signed 16-bit - 0=OK, 1=No data, 2=Parity, 3=Overrun, 4=Framing, 5=Break
Barcode_Timestamp Date/Time - Server time of last good read
Barcode_Trigger Binary tag - Edge 0->1 fires a trigger pulse to the scanner

Attach a global VBScript action to the picture. Open the picture's Event tab and configure the OnComm event of MSComm1 to call a project function OnSerialData().

' ---------------------------------------------------------------
' WinCC Global Action: OnSerialData
' Trigger: MSComm1.OnComm (every time bytes arrive)
' Purpose: parse ASCII barcode line, validate, write to internal tags
' ---------------------------------------------------------------
Function OnSerialData()
    Dim sIn, sClean, i
    Const MAX_LEN = 32
    
    If HMIRuntime.SmartTags("Barcode_Status").Read = 0 Then
        ' already OK, fall through
    End If

    On Error Resume Next
    sIn = HMIRuntime.SmartTags.Item("MSComm1").Input
    If Err.Number <> 0 Then
        HMIRuntime.Trace "MSComm1.Input failed: " & Err.Number & " " & Err.Description & vbCrLf
        Err.Clear
        Exit Function
    End If
    On Error Goto 0

    If Len(sIn) = 0 Then Exit Function

    ' Strip CR / LF / NUL / STX / ETX framing characters
    sClean = sIn
    For i = 1 To Len(sClean)
        Select Case Asc(Mid(sClean, i, 1))
            Case 2, 3, 10, 13, 0  ' STX ETX LF CR NUL
                sClean = Replace(sClean, Mid(sClean, i, 1), "")
        End Select
    Next

    ' Validate: alphanumeric only, max MAX_LEN
    Dim re
    Set re = New RegExp
    re.Pattern = "^[A-Za-z0-9\-\.]{1," & MAX_LEN & "}$"
    If Not re.Test(sClean) Then
        HMIRuntime.SmartTags("Barcode_Status").Write 2  ' parity / validation
        HMIRuntime.Trace "Barcode validation failed: [" & sIn & "]" & vbCrLf
        Exit Function
    End If

    ' Commit to internal tags
    HMIRuntime.SmartTags("Barcode_Last").Write sClean
    HMIRuntime.SmartTags("Barcode_Status").Write 0
    HMIRuntime.SmartTags("Barcode_Timestamp").Write Now
    HMIRuntime.SmartTags("Barcode_Count").Write _
        HMIRuntime.SmartTags("Barcode_Count").Read + 1

    HMIRuntime.Trace "Barcode OK: " & sClean & vbCrLf
End Function
VBScript access to ActiveX: In WinCC V7.x the ActiveX object is reachable as HMIRuntime.SmartTags.Item("MSComm1") when the control was placed on a picture with object name MSComm1. Do not reference the control from a global VBS action that runs without picture context - the object is not in scope. Use the picture-level Event action of the control itself.

Polling on a 5-Minute Cycle

There are two common scan modes: autonomous (scanner fires on object detect) and host-triggered (the WinCC picture pulses the trigger line). For the user's "scan every 5 minutes" requirement, host-triggered mode is more deterministic.

  1. In the picture add a WinCC Timer control (or a global C action) with a 5-minute interval (300,000 ms).
  2. On Timer Event, run the VBScript snippet below to send a 50 ms trigger pulse through the MSComm Output property or by toggling RTS via MSComm1.RTSEnable:
    Sub On5MinTick()
        ' Method A: software trigger via serial command (Honeywell, Zebra, Datalogic)
        HMIRuntime.SmartTags.Item("MSComm1").Output = Chr(13)  ' <CR>
        HMIRuntime.SmartTags("Barcode_Trigger").Write 1
        
        ' Method B: hardware trigger on RTS (Pin 7)
        ' HMIRuntime.SmartTags.Item("MSComm1").RTSEnable = True
        ' HMIRuntime.SmartTags.Item("MSComm1").RTSEnable = False
    End Sub
  3. If the scanner is configured to presentation mode (continuous trigger when enabled), the timer is redundant - simply let OnComm drive the storage and let the scanner's own internal beeper confirm the read.
  4. Use HMIRuntime.SmartTags("Barcode_Trigger").Write 0 from a separate 200 ms timer to clear the trigger tag for edge detection upstream.

Storing Scans in Internal Tags and Archives

The Barcode_Last internal tag can be consumed by:

  • I/O field on the picture - bind an I/O Field output to Barcode_Last. Set Update to "On change" so Runtime refreshes the moment the tag is written.
  • Tag Logging - in the Tag Logging editor, create a new archive BarcodeArchive of type TagLoggingSlow (1 s cycle) and add Barcode_Last, Barcode_Count, Barcode_Status with event-based acquisition on tag change.
  • User Archives - for SQL-style persistence, route the value through a UA field using HMIRuntime.SmartTags.Item("UA_Barcode").Value = sClean after binding the user archive column.
  • Alarm Logging - raise a message of class System, With Acknowledgement with process value Barcode_Last to get a chronological scan log in the WinCC AlarmView control.

Verification and Runtime Testing

  1. From the engineering station, open HyperTerminal, PuTTY (serial mode 9600-8-N-1) or the free WinCC Tag Simulator to confirm the scanner itself is emitting data on COM1.
  2. In Graphics Designer, press F5 to test the picture locally. Click in the I/O field bound to Barcode_Last to confirm output updates.
  3. Open the WinCC ApDiag tool (Apdiag.exe in the WinCC installation directory) and filter the Connection view. Verify that the MSComm control initializes without error 0x800A0E7A (ADO could not find provider).
  4. Trigger a scan and inspect the Runtime trace (WinCC Explorer > Tools > Trace): the line Barcode OK: 12345678 should appear in WinCC_Sys_.log on the diagnostics path.
  5. Check the internal tag value with the online tag table (Tag Management > right-click > Display Tag Values). Verify Barcode_Count increments by exactly 1 per good read.
  6. Verify the archive using WinCC Archive Viewer or SQL Viewer. The BarcodeArchive should show 1 row per accepted scan with timestamp.
  7. Stress test: trigger 200 scans in 60 seconds and confirm the Runtime CPU stays below 25% on a Core i5 and the tag archive has no gaps. This validates the RThreshold / InputLen tuning.

Troubleshooting Matrix

Symptom Likely cause Diagnostic Fix
MSComm missing from Insert ActiveX dialog OCX not registered, or 32/64 bit mismatch Run regsvr32 mscomm32.ocx from elevated CMD Re-register in SysWOW64 on 64-bit OS
Runtime error 0x80040112 (CLASS_E_CLASSNOTREG) AV stripped the CLSID key Check HKCR\CLSID\{648A5600-2C6E-101B-82B6-0000C0BBA6B5} Add mscomm32.ocx to AV exclusion, re-register
PortOpen fails with error 8005 COM port in use, wrong number, or USB device detached Device Manager; check mode COM1 from CMD Close HyperTerminal; assign a stable COM number via Device Manager
OnComm fires but Input is empty Scanner using binary mode, RThreshold too high, wrong terminator Capture traffic with HHD Free Serial Port Monitor Set InputMode=0, RThreshold=1, terminator CR/LF
Garbled characters (e.g. Ø instead of A) Baud / parity / data bit mismatch Verify scanner configuration sheet Match Settings string to scanner config
Triggers fire continuously, CPU at 100% RThreshold=0 with high noise Watch process explorer Set RThreshold=1 and decouple via internal tag
Tag value never updates Global action cannot see picture-bound ActiveX Trace shows nothing Move handler to picture's OnComm event
Works in Graphics Designer, not in Runtime client OCX not installed on client; WinCC client is 32-bit Check client log Deploy mscomm32.ocx to every RT client
Error 8020 in trace (comPortInUse) Two pictures opening the same COM port Search project for CommPort=1 Open COM in only one master picture; consume the tag globally
Data appears with leading 0x02 0x30 bytes Scanner adds AIM/ID symbology identifier HHD dump Disable symbology ID in scanner config or strip in VBS

Security and Hardening Notes

Because mscomm32.ocx is a Win32 COM component, it operates in-process with the WinCC Runtime. The following hardening steps are recommended on a production deployment.

  • Use a dedicated USB-to-RS232 adapter (FTDI FT232H) and physically disable the COM port enumeration for any non-essential serial device via Group Policy.
  • Set the scanner to inter-character timeout ≥ 50 ms and disable all symbologies that are not used (Code 39, Code 128, QR, DataMatrix as applicable). This shrinks the attack surface for malicious barcode injection.
  • Whitelist the barcode format in the VBS validator (e.g., only allow 10-13 digit numeric for shipping labels). Anything else is rejected and logged to Barcode_Status.
  • Apply Windows Defender Application Control (WDAC) to permit only signed OCX components. mscomm32.ocx is signed by Microsoft but the signing certificate chain is now legacy - plan a migration to WinCC Unified's SysSerial or to a vendor-supported OPC UA bridge long term.
  • Lock the engineering station so users cannot right-click the picture and use the Properties dialog to inject arbitrary VBScript.

Alternatives and Migration Path

If the mscomm32.ocx path is blocked by corporate security, the following alternatives deliver the same result with a cleaner architecture.

Approach Mechanism Pros Cons
CP340 / CP341 in S7-300/400/1500 Point-to-point module on PLC, expose to WinCC via S7 driver Industrial, isolated, deterministic Requires a free slot in the PLC, more hardware
SIMATIC RF/RFID serial gateway Vendor gateway converts RS232 to S7 / OPC UA No OCX Cost, single vendor lock-in
Third-party OPC UA serial bridge (Kepware, Softing, KEPServerEX) Daemon reads COM, exposes OPC UA server Modern, signed, supports many devices Extra license, extra service to maintain
WinCC Unified (V16+) SysSerial namespace Native RT scripting API, no ActiveX Long-term supported, no OCX dependency Requires V16+ project migration
Custom Windows service in C# / .NET Service reads COM, writes to WinCC internal tag via WinCC ODK Full control More development effort, requires WinCC ODK license

Frequently Asked Questions

Why does my COM1 read return only garbage characters in WinCC Runtime?

Baud rate, parity, data bits, or stop bits on the scanner do not match the MSComm1.Settings string. Verify the scanner's actual configuration via its programming barcodes or serial console (most Honeywell, Zebra, and Datalogic devices reply to a CR/LF query at 9600-8-N-1 by default), then set MSComm1.Settings = "9600,N,8,1" to match.

How do I trigger a barcode read every 5 minutes automatically?

Place a WinCC Timer with interval 300,000 ms on the picture. On its event, write a CR (Chr(13)) to MSComm1.Output or toggle MSComm1.RTSEnable for 50 ms. Most industrial scanners interpret either as a manual trigger pulse.

Can the same COM port be opened from multiple WinCC pictures?

No. A single physical COM port can only be opened by one MSComm instance at a time. Open the port in one master picture (e.g., Start.pdl) and consume Barcode_Last from any other picture via the standard tag interface.

Is mscomm32.ocx supported on 64-bit Windows with WinCC 7.x?

Yes, but you must copy the OCX to %SystemRoot%\SysWOW64\ and register it from an elevated command prompt using the 32-bit regsvr32.exe. The WinCC Runtime process is 32-bit, so it loads the WOW6432 registration. Do not place the OCX in System32 on a 64-bit host.

How do I migrate from mscomm32.ocx to WinCC Unified?

WinCC Unified (V16 and later) exposes SysSerial.open(), SysSerial.read(), and SysSerial.close() directly in JavaScript and C, eliminating the ActiveX dependency. Migration is project-by-project: redefine the barcode tag as an internal Unified tag, replace the VBScript handler with a Unified script, and remove the OCX installation step from the deployment image.

Back to blog