WinCC VBS ADODB/ODBC Reconnection Failure After SQL Server Restart: Root Cause and Fix
A SIMATIC WinCC V7 runtime global VBScript that uses an ADODB.Connection over an ODBC DSN to Microsoft SQL Server opens cleanly at startup, writes its heartbeats, reads recipe data, and looks perfectly healthy. The first time the SQL service is restarted, the network interface is pulled, or the SQL host is rebooted, every subsequent call into the ADODB layer raises [Microsoft][ODBC SQL Server Driver]Communication link failure and the script never recovers on its own. Recovery happens only when WinCC unloads and reloads the script, which is exactly what a re-save in the Global Script editor implicitly triggers. This reference documents why the COM object stays locked in a faulted state, the ODBC driver behaviour that drives the long reconnect window, and a complete object-recreation pattern that brings the runtime back inside seconds instead of minutes.
The pattern applies to any WinCC V7.x project that uses ODBC connectivity from VBScript, including WinCC V7.3, V7.4, V7.4 SP1, V7.5, V7.5 SP1, and V7.5 SP2. It also applies to WinCC V8 where the same VBScript host is used for classic SCADA functions. The TIA Portal WinCC Professional C-script API has a different connection model and is not affected by the same COM lifetime trap.
1. Problem Summary
WinCC VBS global actions are the standard mechanism for cyclical housekeeping in a WinCC V7.x SCADA project. The pattern is well known: declare a module-level objConnection of type ADODB.Connection, call Open once at the top of the project or in an Application_OnStart sub, and reuse the object from every triggered action.
That pattern breaks the moment the SQL Server or the network path is interrupted:
- The first post-failure query raises
Run-time error '-2147467259 (80004005)'with description[Microsoft][ODBC SQL Server Driver]Communication link failure. The ODBC SQL state is08S01. - A subsequent
objConnection.Opencall does not re-establish the session. VBScript either returns success without doing anything or raises the same failure, depending on the cached COM state of the object. - The WinCC runtime continues to call the heart-beat sub every five seconds. The script enters a tight error loop that lasts from a few seconds up to twenty minutes before the connection is reported usable again.
- The only manual workaround is to edit and re-save the VBS script. That action forces WinCC to tear down the VBScript engine and reload the global script module, which rebuilds the
objConnectionfrom scratch. - Two independent ADODB connections against the same SQL instance, written from the same script project, recover at different times. One reconnects inside ten minutes; the other takes more than twenty minutes. This is not a code defect; it is a property of the ODBC driver pool underneath the script.
[Microsoft][ODBC SQL Server Driver]Communication link failure is ODBC SQL state 08S01. It indicates that the SQL Server has dropped the session, the network path has been reset, or the driver has lost its socket handle. It is recoverable only by allocating a new ADODB.Connection object and a new ODBC session; the existing object must be released.2. Error Signature and Symptoms
Two error surfaces appear in a failing WinCC VBS connection. The first is the VBScript-level error raised by ADODB. The second is the ODBC-level SQL state and native error code returned from the driver.
| Layer | Code | String | Meaning |
|---|---|---|---|
| VBScript | -2147467259 (80004005) | Automation error / Unspecified error | COM method failed; ADODB did not translate to its own error number |
| ADO Error | err.Number = 0x80004005 | Provider-specific error | Provider (MSDASQL / ODBC driver) returned a native error |
| ODBC SQL State | 08S01 | Communication link failure | Driver-to-server transport broken |
| ODBC Native | 0 or 10054 (WSAECONNRESET) | Connection reset by peer | TCP socket closed by the remote side or by an intermediate device |
| SQL Server log | Error 10054 / 233 | A connection was successfully established with the server, but then an error occurred during the pre-login handshake | Server side observation of the dropped session |
The visible behaviour in the WinCC Explorer is one or more of the following:
-
LastHBandtmpHBRecipetags stop matching in the internal state script. The condition is captured correctly by the cyclic action. - Error dialogs logged in
WinCC_RT_xx.log(typically under<ProjectPath>\ScriptLib\Logs) repeatedly report the80004005failure. - SQL Server Management Studio's Activity Monitor or the dynamic management view
sys.dm_exec_connectionsshows the WinCC client session disappearing at the moment of failure and not returning for the duration of the symptom. - The
Connection.Stateproperty of the ADODB object readsadStateClosedafter a failed query, but the next.Openon the same object does not produce a working session. - The Windows ODBC trace (
odbcad32.exeon 32-bit, with tracing enabled inHKLM\SOFTWARE\ODBC\ODBCINST.INI\ODBC Tracing) showsSQLDisconnectnever being called andSQLDriverConnectreturningSQL_INVALID_HANDLEon the cachedSQLHDBC.
3. Root Cause Analysis
Three layers cooperate to produce the symptom. Each layer holds on to its own state, and each layer must be released in order for a clean reconnect to occur.
3.1 Component Topology
3.2 VBScript / ADO COM Object Lifetime
VBScript executes inside WinCC's scripting host in a Single-Threaded Apartment (STA). The ADODB.Connection object is a COM object that wraps the ODBC handle set. When objConnection.Open "DSN=MyDSN;..." succeeds, ADODB internally calls SQLAllocHandle(SQL_HANDLE_DBC), SQLDriverConnect, and any number of SQLSetConnectAttr calls. The ODBC handle and the underlying TCP socket live inside the ADODB COM object.
When the socket dies, the ODBC driver marks the connection handle as SQL_CD_FALSE (not connected) and the ADODB object enters an error state. Calling .Open on a faulted ADODB object does not reallocate a new ODBC handle set: the IConnectionPointContainer still points at the same interface, and VBScript can see the call return as if it succeeded. The internal SQLHDBC remains invalid.
The VBScript engine has no reference-counted destructor that would call objConnection.Close and Set objConnection = Nothing when the runtime fails. The COM object stays alive in the script engine, with a dangling ODBC handle, until the VBScript engine itself is unloaded. WinCC unloads the VBScript engine only when the project is reloaded, the runtime is restarted, or a script module is re-saved in the editor.
3.3 ODBC Driver Manager Connection Pool
The Microsoft ODBC Driver Manager maintains a per-DSN connection pool unless SQL_ATTR_CONNECTION_POOLING is explicitly set to SQL_CP_OFF. The pool serves cached SQLHDBC handles to callers and reclaims them when callers call SQLDisconnect. The CPTimeout value in HKLM\SOFTWARE\ODBC\ODBCINST.INI\ODBC Connection Pooling (and the 64-bit equivalent) controls how long an unused pooled connection is retained before it is discarded. The default is 60 seconds.
When a pooled connection's underlying socket has died, the pool cannot tell the difference until the next user attempts a query. At that point the pool discards the dead handle and allocates a fresh one. The visibility of that discard event to the calling VBScript is asynchronous and depends on the pool's internal heartbeat, which is what produces the unpredictable 10-second to 20-minute reconnect window observed in the field. See Microsoft ODBC error codes reference for the canonical SQL state table.
3.4 Microsoft SQL Server Session State
SQL Server itself drops the worker thread and frees the session when it sees a TCP reset. The corresponding row in sys.dm_exec_connections is removed immediately. From the WinCC script side, the next objConnection.Execute call sees 08S01 and the script enters the error loop. The TCP retransmit timeout on Windows defaults to 5 seconds with up to 5 retransmits, which contributes to the lower bound of the reconnect window.
Together, these three layers mean the VBScript code must explicitly perform the following sequence to recover: discard the COM object, force the ODBC pool to give up the dead handle, then re-create the COM object and re-allocate the ODBC session. None of these steps is implicit in VBScript or in ADODB. The Microsoft ADO Connection object documentation describes the State property and the Open method semantics; the State property reflects the cached status and does not re-probe the network.
4. WinCC VBScript Runtime and ADO Behaviour
The WinCC V7 scripting environment is documented in the WinCC V7.5 information system. The relevant constraints for database work are:
- The VBS engine is started per
GlobalScript.dllhost. The host loads each global script action and each standard function in a shared script context. - Module-level
Dimdeclarations in global actions live for the lifetime of the script host. They are not re-initialised between two consecutive invocations of the same cyclic action. - The
Application_OnStartandApplication_OnEndevents are the only automatically triggered events at project startup and shutdown. Cyclic actions are user-defined timers in the WinCC Explorer under Global Script > Actions. - There is no
finallyconstruct in VBScript. Error handling is done withOn Error Resume Nextand explicitErr.Number/Err.Descriptionchecks. Every routine that touches ADODB must wrap the call inOn Error Resume Nextand inspectErr.Numberafter the call. - The VBS engine does not surface
WIN32_FIND_DATAor Windows Sockets errors directly. They are wrapped by ADODB and by the ODBC driver manager as provider-specific errors. The only way to distinguish a 08S01 from a permission error (42000) or a syntax error (37000) is to read theErr.Descriptionstring or theADODB.Connection.Errorscollection. -
Err.Clearmust be called immediately before every ADODB call that is being protected byOn Error Resume Next; otherwise the VBS engine reuses a stale error from a prior call and the script makes the wrong decision. - The script engine runs each cyclic action on a single STA thread. A blocking call inside a cyclic action blocks every other cyclic action in the project.
ConnectionTimeoutandCommandTimeoutmust be set aggressively to prevent the script host from being held hostage by a dead socket.
On Error Goto 0 follows the WSH reference, not the CLR reference.5. Microsoft ODBC SQL Server Driver Behaviour
When the WinCC script calls objConnection.Execute "SELECT ..." against a connection whose socket has died, the driver returns SQL_SUCCESS_WITH_INFO and a diagnostic record whose SQL state is 08S01. The behaviour is documented by Microsoft in the ODBC appendix for SQL state values. The same SQL state covers a wide range of transport-level failures:
| SQL State | Native Code | Driver String | Likely Cause |
|---|---|---|---|
| 08S01 | 0 | Communication link failure | TCP RST from server, server restart, network reset |
| 08S01 | 10054 (WSAECONNRESET) | Connection reset by peer | Remote side closed socket |
| 08S01 | 10060 (WSAETIMEDOUT) | Connection timed out | Firewall drop, routing failure |
| 08S01 | 10061 (WSAECONNREFUSED) | Connection refused | SQL service not listening on target port |
| 08S01 | 64 (ERROR_NETNAME_DELETED) | Network name no longer available | NIC reset, switch port down |
| HYT00 | 0 | Timeout expired | ConnectionTimeout or QueryTimeout reached |
| 08001 | 0 | Client unable to establish connection | DSN missing, driver not installed, server not found |
| 08007 | 0 | Transaction resolution unknown | Connection lost during in-flight transaction |
| 40001 | 1205 | Deadlock victim | SQL Server transaction killed by the deadlock monitor |
The driver also has parameters that control handshake timing and auto-recovery behaviour:
-
ConnectionTimeout: time the driver waits for the connect handshake. Default 15 seconds for ODBC Driver 17 for SQL Server, 30 seconds for older versions. Configurable on the
objConnectionas theConnectionTimeoutproperty. -
QueryTimeout: time the driver waits for a query to return. Defaults to driver-specific, often 30 seconds. Configurable on the
objConnectionas theCommandTimeoutproperty. -
Connection Lifetime: the ODBC driver-manager hint, in seconds, after which a pooled connection is discarded even if it is healthy. Useful for forcing predictable reconnect windows. Set via the connection string:
Connect Timeout=15;Connection Lifetime=600.
None of these parameters restore a dead session. They only control the wait time for the next attempt. Restoration requires a brand-new ODBC session and, on the WinCC side, a brand-new ADODB COM object.
6. Affected Versions and Configuration Prerequisites
The problem is independent of WinCC version. It has been observed on WinCC V7.3, V7.4, V7.4 SP1, V7.5, V7.5 SP1, and V7.5 SP2. It is not specific to a particular ODBC driver. It has been reproduced with the legacy "SQL Server" driver (sqlsrv32.dll) shipped with Windows, the modern "ODBC Driver 17 for SQL Server" (msodbcsql17.dll), and "ODBC Driver 18 for SQL Server" (msodbcsql18.dll). The full WinCC V7.5 documentation set is available at the Siemens Industry Online Support portal.
Prerequisites before applying the fix below:
- A working 32-bit ODBC DSN named in the connection string. The WinCC RT runs as a 32-bit process on 64-bit Windows, so the DSN must be created in
C:\Windows\SysWOW64\odbcad32.exe, not in the 64-bit ODBC Administrator. - The Windows account under which the WinCC RT service runs must have
publicplusdb_datareader/db_datawriteron the target database. SQL authentication is supported but Microsoft Entra (formerly Azure AD) authentication requires ODBC Driver 17.3 or newer and explicit parameters (Authentication=ActiveDirectoryPassword) in the connection string. - The SQL Server network configuration must have TCP/IP enabled in SQL Server Configuration Manager. The SQL Server Browser service must be running if the connection uses a named instance and a non-standard port.
- The Windows firewall on the SQL Server host must allow inbound 1433/TCP (or the configured port) and 1434/UDP for the Browser service.
- The WinCC station's
KeepAliveTimeregistry value should be lowered to 30000 ms (30 seconds) from the default 7,200,000 ms (2 hours) to make the local TCP stack detect dead sockets promptly. Set inHKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters. - The SQL Server should be started with
-t 692trace flag, or with thedatabase mirroring connection timeoutsp_configure option, to surface the actual handshake failure to the client. This is not required for the fix but it accelerates field diagnosis.
odbcad32.exe from System32 on a 64-bit OS opens the 64-bit catalog, which is not visible to the WinCC RT process and leads to misleading "Data source name not found and no default driver specified" errors.7. Connection Lifecycle and State Machine
The fix is to make the script treat the connection as a resource that must be acquired and released per transaction, with an explicit health check that recreates the object on demand. The lifecycle has five states and the transitions are deterministic.
8. Step-by-Step Implementation
The following VBScript is a working pattern to paste into a WinCC V7 Global Action. The action is triggered every five seconds by a standard cyclic action in the WinCC Explorer. The same module is reused by every database-touching action in the project.
Step 1 - Declare the module-level state. Place these declarations outside of any sub, at the top of the global action:
' Module-level state for the connection holder
Dim objConnection
Dim g_ConnectionString
Dim g_LastReconnectAt
Dim g_ConsecutiveFailures
Dim g_ReconnectInProgress
Dim g_NextReconnectAllowedAt
g_ConnectionString = "DSN=WinCC_SQL;UID=wincc_user;PWD=<password>;" & _
"DATABASE=RecipeDB;APP=WinCC_RT;" & _
"WSID=" & CreateObject("WScript.Network").ComputerName & ";" & _
"Connect Timeout=15;Connection Lifetime=600"
g_LastReconnectAt = 0
g_ConsecutiveFailures = 0
g_ReconnectInProgress = False
g_NextReconnectAllowedAt = 0
Step 2 - Implement the connection holder function. This is the only place in the project that touches the raw ADODB object:
Function EnsureConnection()
On Error Resume Next
If g_ReconnectInProgress Then
EnsureConnection = False
Exit Function
End If
' Backoff: respect the cooldown window
If Timer < g_NextReconnectAllowedAt Then
EnsureConnection = False
Exit Function
End If
' --- Health probe ---
If Not (objConnection Is Nothing) Then
If objConnection.State = 1 Then
' adStateOpen = 1
Err.Clear
objConnection.Execute "SELECT 1"
If Err.Number = 0 Then
g_ConsecutiveFailures = 0
EnsureConnection = True
Exit Function
Else
' record the first ADODB error for diagnostics
HMIRuntime.Trace "EnsureConnection: probe failed " & _
Err.Number & " " & Err.Description & vbCrLf
End If
End If
End If
' --- Rebuild path ---
g_ReconnectInProgress = True
' Step A: destroy the old COM object explicitly
If Not (objConnection Is Nothing) Then
Err.Clear
objConnection.Close
Set objConnection = Nothing
End If
' Step B: short pause to let the ODBC Driver Manager release the dead
' SQLHDBC handle from the pool. 1.5 s is field-proven.
Dim t : t = Timer
Do While Timer - t < 1.5
' cooperative yield; no Sleep in VBScript
Loop
' Step C: build a brand-new COM object
Err.Clear
Set objConnection = CreateObject("ADODB.Connection")
If Err.Number <> 0 Then
HMIRuntime.Trace "EnsureConnection: CreateObject failed " & _
Err.Number & " " & Err.Description & vbCrLf
Set objConnection = Nothing
g_ReconnectInProgress = False
g_NextReconnectAllowedAt = Timer + 5
EnsureConnection = False
Exit Function
End If
objConnection.ConnectionTimeout = 15
objConnection.CommandTimeout = 30
objConnection.CursorLocation = 3 ' adUseClient for read-heavy paths
' Step D: open the connection
Err.Clear
objConnection.Open g_ConnectionString
If Err.Number <> 0 Then
HMIRuntime.Trace "EnsureConnection: Open failed " & _
Err.Number & " " & Err.Description & vbCrLf
Set objConnection = Nothing
g_ReconnectInProgress = False
g_ConsecutiveFailures = g_ConsecutiveFailures + 1
g_NextReconnectAllowedAt = Timer + (30 * g_ConsecutiveFailures)
EnsureConnection = False
Exit Function
End If
g_LastReconnectAt = Now
g_ConsecutiveFailures = 0
g_ReconnectInProgress = False
EnsureConnection = True
End Function
Step 3 - Implement the cyclic health check. Register this sub as a global action with a 5-second trigger:
Sub HeartBeat_Recipe()
On Error Resume Next
If Not EnsureConnection() Then
g_ConsecutiveFailures = g_ConsecutiveFailures + 1
If g_ConsecutiveFailures > 3 Then
HMIRuntime.Trace "HeartBeat_Recipe: SQL unreachable for " & _
g_ConsecutiveFailures & " cycles" & vbCrLf
End If
Exit Sub
End If
Err.Clear
objConnection.Execute "UPDATE dbo.RecipeHeartBeat SET LastHB = GETDATE() " & _
"WHERE ServerName = 'Recipe'"
If Err.Number <> 0 Then
HMIRuntime.Trace "HeartBeat_Recipe: UPDATE failed " & _
Err.Number & " " & Err.Description & vbCrLf
' Force the connection holder to rebuild on the next call
Set objConnection = Nothing
End If
End Sub
Step 4 - Add cleanup in Application_OnEnd. Place this in the project-level actions:
Sub Application_OnEnd()
On Error Resume Next
If Not (objConnection Is Nothing) Then
objConnection.Close
Set objConnection = Nothing
End If
End Sub
Step 5 - Wrap the ADO Errors collection. For surfaces where the provider returns multiple errors, drain the Errors collection explicitly:
Function DumpAdoErrors(conn)
Dim s, e
s = ""
If Not (conn Is Nothing) Then
For Each e In conn.Errors
s = s & "[" & e.SQLState & "] " & e.Description & vbCrLf
Next
End If
DumpAdoErrors = s
End Function
9. Handling Multiple Parallel Connections
The pattern above is duplicated for every independent connection. The two connection holders in the original symptom - "Recipe" and "Spb" - must each own their own COM object and their own objConnection variable. They must not share the object, because the ODBC pool may have a valid handle for one DSN and a dead handle for another at the same moment.
| Connection | Module Variable | DSN | Database | Heartbeat Sub | Trigger Interval |
|---|---|---|---|---|---|
| Recipe | objConnectionRecipe | WinCC_SQL_Recipe | RecipeDB | HeartBeat_Recipe | 5 s |
| Spb | objConnectionSpb | WinCC_SQL_Spb | SpbDB | HeartBeat_Spb | 5 s |
If two connection holders write to the same DSN but a different database, they can still share an objConnection, but only as long as the connection string includes DATABASE=.... If the databases are different, separate DSNs are recommended to keep the ODBC pool small and the failure isolation clean.
A common field pattern is to use a single base sub that takes the target variable by reference, but VBScript's ByRef is incompatible with the COM object lifetime contract and produces subtle leak bugs. The duplication is the correct pattern.
10. Connection Health Check and ADO Error Collection
The SELECT 1 probe used in EnsureConnection is the canonical round-trip check. A few details matter:
- Use a constant integer literal. Do not use a parameterised query: a parameterised query forces the ODBC driver to negotiate parameter metadata, which masks certain types of failure.
- Open a fresh
ADODB.Recordsetto read the result if the caller needs the value. Do not useobjConnection.Executewith theRecordsAffectedargument, because the driver may suppress diagnostics on a no-rowset result. - Combine the probe with the
objConnection.Statecheck. The state is cheap to read; if the COM object has been closed externally,State = 0(adStateClosed) tells you to rebuild without spending a round trip. - Wrap the probe in a
Withblock to avoidIs Nothingissues during the VBScript teardown phase. VBScript can race the script host during shutdown and returnobjConnection Is Nothing = Falsefor an already-destroyed object. - Inspect
objConnection.Errors.Countafter every failed call. The Errors collection can hold multiple records; the first record is usually the most relevant. Clear the collection withobjConnection.Errors.Clearbefore the next operation to avoid reading stale errors. - Use
HMIRuntime.Tracefor the diagnostic output.MsgBoxblocks the VBScript thread and will stall every other cyclic action in the project, including the alarm handling actions.
11. Verification Procedure
After the new code is in place, validate the recovery path with the following procedure:
- Open WinCC RT with the new global actions deployed. Verify the heartbeats are visible in the target tables by querying
SELECT LastHB FROM dbo.RecipeHeartBeatfrom SQL Server Management Studio. - Stop the SQL service on the host:
NET STOP MSSQLSERVER. WatchHMIRuntime.Tracein the diagnostic window. Expect three "SQL unreachable" log lines, then a sustained "Open failed" line with the 08S01 description. - Start the SQL service:
NET START MSSQLSERVER. - Watch the
g_ConsecutiveFailurescounter (expose it to an internal tag for this test). Expect the next 5-second cycle to clear the counter to 0 and write a successful heartbeat. - Repeat the test with a physical cable pull on the WinCC station instead of a service restart. The recovery path is identical.
- Verify in SQL Server Management Studio, against the dynamic management view
sys.dm_exec_connections, that the WinCC session re-appears inside 30 seconds of the SQL service coming back. If it does not, the problem is in the rebuild path, not in the ODBC pool. - Run a 24-hour soak test with the cyclic action at 5 seconds. Confirm zero false disconnects and zero false positives from the rebuild path.
- Repeat the test with a deliberately slow network: introduce 200 ms RTT with a network shaper such as
tc(Linux) orClumsy(Windows). Confirm the connection still recovers inside the configuredCommandTimeout.
12. Field-Tested Hardening and Best Practices
The following items are not required to fix the symptom but they prevent the related class of failures from masking the same root cause in the future:
- Set
objConnection.ConnectionTimeout = 15andobjConnection.CommandTimeout = 30on every new connection. Without these, the driver falls back to the system default and a hung session can lock the script thread for the default 30 seconds. - Set
objConnection.CursorLocation = 3(adUseClient) for read-heavy workloads. Client-side cursors buffer rows in the ADODB object, which makes the nextEOF/BOFcheck independent of the network state. For write-heavy workloads, leave it at the default (adUseServer). - Add
Application_OnEndcleanup:If Not (objConnection Is Nothing) Then objConnection.Close : Set objConnection = Nothing. This makes WinCC runtime restarts leave the ODBC pool in a clean state. - Disable ODBC connection pooling for time-critical connections. The pool adds latency to the reconnect path and is rarely useful for a single-process WinCC runtime. Set the registry value
HKLM\SOFTWARE\ODBC\ODBCINST.INI\CPTimeoutto 0, or passOLE DB Services=-4in the connection string to opt out of OLE DB resource pooling, which is what ADODB uses by default. - Use SQL authentication with a dedicated least-privilege account, not the local SYSTEM account. This separates the WinCC service identity from the SQL service identity and makes the connection strings easier to audit.
- Enable SQL Server's
auto close= false on the target database. Withauto close= true, the first connection after a service restart pays a database warm-up cost that pushes the reconnect window past the typical 5-second action interval. - Add a
Connection Lifetimehint via the connection string:Connect Timeout=15;Connection Lifetime=600forces the driver to drop and rebuild pooled connections older than 10 minutes. This makes the recovery time predictable and matches the WinCC VBS restart cycle. - Add a
WSIDhint in the connection string (set to the WinCC station's hostname). This makes the WinCC session trivial to identify insys.dm_exec_connections.hostnameand in SQL Server's profiler traces. - For redundant WinCC stations, use a Windows Failover Cluster or an AlwaysOn Availability Group listener, not a round-robin DNS entry. The latter causes the WinCC client to cache the first IP and ignore subsequent failures.
- Lower
KeepAliveTimeon the WinCC station to 30000 ms and enableTCPAckFrequencyif you are running on a slow link. This makes the local TCP stack detect a dead SQL socket inside a minute instead of waiting the Windows default of two hours.
13. Troubleshooting Matrix
| Symptom | Likely Cause | Verification | Fix |
|---|---|---|---|
| Reconnect works on script save only | Stuck COM object reference, not the ODBC pool | Inspect objConnection.State after a failure |
Add the explicit Close / Set ... = Nothing path |
| Two connections recover at different times | ODBC pool has cached state per-DSN | Compare sys.dm_exec_connections for both sessions |
Use one connection holder per DSN; do not share the COM object |
| Reconnect window is 10 s - 20 min, non-deterministic | ODBC pool CPTimeout cycling |
Read HKLM\SOFTWARE\ODBC\ODBCINST.INI\CPTimeout
|
Set CPTimeout = 0 or pass OLE DB Services=-4 in the connection string |
| Reconnect never happens, even after 20 min | SQL Server Browser not running, port blocked, or DNS issue | Test with osql -S server\instance -E from the WinCC host |
Fix the underlying network or DNS issue first; the script will not help if the driver cannot reach the server |
| Error 18456 (login failed) after reconnect | The SQL account was locked out by too many retries | Check SQL Server error log for 18456 | Reduce the script's reconnect rate; consider CHECK_POLICY = OFF on the SQL account for a WinCC service identity |
| Reconnect works in VBScript editor test but not in RT | Editor runs in a different COM host than RT | Compare the process model of Wscript.exe vs the WinCC RT process |
Always test in the RT; the editor hides COM lifetime issues |
| CPU spikes on WinCC station after a SQL outage | Tight retry loop without backoff | Task Manager on the WinCC host during the failure window | Add the exponential backoff described in step 2 of the implementation |
| Reconnect succeeds but first query returns zero rows | Database warm-up; auto close is on | Check sys.databases.is_auto_close_on
|
Set AUTO_CLOSE OFF on the target database |
| Trace log fills with 08S01 entries after a 1-second network blip | TCP keep-alive not enabled; default retransmit is 2 hours | Check KeepAliveTime in registry |
Set KeepAliveTime=30000 and restart |
| Connection works for one WinCC station but not a second on the same network | Per-station firewall rule or per-station credential issue | Compare osql test results between the two stations |
Align firewall rules and SQL logins; do not share the WinCC service account |
Frequently Asked Questions
Why does editing and saving the VBS script reconnect the ADODB connection?
Saving the script in the Global Script editor causes WinCC to unload and reload the VBScript engine, which in turn releases the module-level objConnection reference. The dead COM object is destroyed and the next Open allocates a fresh ODBC session. It is the same effect as a WinCC RT restart, but it is a side effect of the editor, not a recovery mechanism.
Why does the same code reconnect in 10 seconds sometimes and 20 minutes other times?
The Microsoft ODBC Driver Manager maintains a per-DSN connection pool with a CPTimeout default of 60 seconds. The pool does not eagerly discover that a cached handle is dead; it discovers it on the next attempt, and the pool's internal cleanup is asynchronous. The actual recovery time is determined by the race between the WinCC script's next call and the pool's next cycle, which is non-deterministic and depends on system load.
Can I use the WinCC OLE DB Provider instead of ADODB/ODBC?
The WinCC OLE DB Provider reads from the WinCC archive database, not from a user-defined SQL Server. For connectivity to your own SQL Server database, ADODB over ODBC is still the standard path. For connectivity to the WinCC archive, use the WinCC OLE DB Provider directly; it has its own reconnection semantics that are documented separately in the WinCC V7.5 information system.
Does the same problem occur with WinCC Professional (TIA Portal) C-scripts?
The C-script API in WinCC Professional uses a different connection model. C-script SQLExecute calls are routed through the WinCC database layer, which manages its own connection pool and reconnect logic. The ADODB/ODBC COM-object lifetime trap does not apply to C-script in the same way. The pattern in this article applies only to the VBScript global action environment in WinCC V7 RT and the WinCC V8 SCADA runtime.
What is the recommended retry interval for WinCC VBS global scripts?
For heartbeats, 5 seconds is the standard pattern. For the reconnect attempt itself, 5 seconds is too aggressive after a sustained outage; 30 seconds with exponential backoff up to 5 minutes is the field-proven default. Never set the retry interval below 1 second; the ODBC driver needs at least one full ConnectionTimeout window to fail cleanly, and a tighter loop will starve the rest of the script engine.
Which ODBC driver version should I install for SQL Server 2019 or 2022?
Use ODBC Driver 18 for SQL Server on a fresh install. It supports TLS 1.3 by default and provides the Encrypt and TrustServerCertificate connection-string parameters that the WinCC VBScript can pass through. If you must stay on Driver 17, the connection string must include Encrypt=Optional to avoid a hard-fail on the first call.