Connecting WinCC to C# and SQL Server: OPC DA, DCOM, IDB Guide

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

1. Overview

Siemens WinCC (TIA Portal / V7) exposes runtime data through three well-supported channels: an internal OPC DA Server (built-in, no extra license), the Connectivity Pack / WinCC DataMonitor (OLE DB / SOAP / OPC XML / WinCC OLE DB provider), and the Industrial Data Bridge (IDB) add-on for declarative tag-to-database bridging. A C# application can read and write WinCC tags through any of these paths and, in the same process, persist values to Microsoft SQL Server using ADO.NET or the WinCC SQL Provider.

This reference covers all four integration paths, the DCOM configuration required to traverse a LAN, the error matrix that appears in field deployments, and the C# code skeleton for an OPC DA 3.0 client built against OPC Foundation .NET API or OpcNetApi.

Topology assumption: WinCC Runtime is installed on a station reachable from the C# host on TCP port 135 plus the dynamic RPC range (49152-65535 on Windows Server 2008 R2+, 1024-65535 on Windows XP/2003). The WinCC OPC DA Server service runs under the local SYSTEM account or a dedicated OPC user account.

2. Architecture Options

Method Direction WinCC Add-on C# Stack Best For
OPC DA 3.0 (in-process COM) Bidirectional tags None (built-in) OpcNetApi / OPC Foundation .NET Real-time tag read/write, low latency
Connectivity Pack / DataMonitor OLE DB Read-only archive WinCC Connectivity Pack or DataMonitor ADO.NET + OLE DB Provider for WinCC Historical / alarm queries
Industrial Data Bridge (IDB) Bidirectional, declarative IDB license + dongle No client code needed; WinCC config only Plant-floor tag mirroring to SQL
VBS + ADODB inside WinCC Bidirectional, scheduled None (WinCC Scripting) WinCC-side VBScript Lightweight polling without external C# app

For a C# application on a remote workstation, the canonical path is OPC DA over DCOM. For historical reads from the WinCC archive database, use the WinCC OLE DB Provider through Connectivity Pack. For a managed, point-and-click bridge without writing any C# code, use IDB.

3. Prerequisites

  1. WinCC Runtime V7.2 / V7.3 / V7.4 / V7.5 (or WinCC Professional in TIA Portal) installed and running in Runtime.
  2. The WinCC OPC DA Server process OPCServer.WinCC registered as a local COM service. Verify with opcenum.exe on the WinCC station - the server should appear under OPC Servers > OPCServer.WinCC.
  3. Windows user accounts with identical username and password on both the WinCC station and the C# client station. Mismatched credentials are the leading cause of Access is Denied (0x80070005) failures.
  4. DCOM configured on both machines (see Section 9).
  5. For SQL Server integration: SQL Server 2014 / 2016 / 2017 / 2019 (Express is sufficient for tag mirroring), TCP port 1433 reachable, SQL authentication or trusted Windows authentication.
  6. C# development environment: Visual Studio 2010 or later, .NET Framework 4.x or .NET 6/7/8 with COM interop enabled.

4. Method 1 - OPC DA Client in C#

The OPC Foundation .NET API (or the older OpcNetApi.dll) allows any .NET application to enumerate the WinCC OPC server, browse tags, subscribe to data changes, and synchronously read/write values.

4.1 Add References

  • OpcNetApi.dll (v2.x) - browse, sync I/O, subscription
  • OpcNetApi.Com.dll - COM interop wrapper
  • Add using Opc;, using Opc.Da;

4.2 Connect to WinCC OPC Server

using Opc;
using Opc.Da;

// Replace 192.168.2.252 with the WinCC Runtime station IP or hostname
string serverUrl = "opcda://192.168.2.252/OPCServer.WinCC";

Opc.Da.Server server = null;
try
{
    server = new Opc.Da.Server(new OpcCom.Factory(), null);
    server.Url = new Opc.URL(serverUrl);
    server.Connect();
    // server.IsConnected == true on success
}
catch (OpcConnectException ex)
{
    // 0x80070005 = Access Denied (DCOM)
    // 0x80040154 = Class not registered (OPC service not running)
    // 0x800706BA = RPC server unavailable (firewall / service down)
    Console.WriteLine($"OPC connect failed: 0x{ex.Result.Code:X8}");
}

4.3 Browse and Read Tags

// Browse the flat namespace (use BrowseFilters.Flat)
BrowsePosition position = null;
BrowseElement[] elements = server.Browse(
    new ItemIdentifier(""),
    new BrowseFilters { BrowseFilter = browseFilter.flat, ElementNameFilter = null },
    out position);

foreach (BrowseElement el in elements)
{
    Item item = new Item(new ItemIdentifier(el.ItemName), true, 0);
    ItemValueResult[] result = server.Read(new Item[] { item });
    Console.WriteLine($"{el.ItemName} = {result[0].Value}");
}

4.4 Subscribe to Data Changes

Subscription subscription = null;
SubscriptionState state = new SubscriptionState
{
    Name = "WinCC_Sub",
    Active = true,
    UpdateRate = 250,           // ms
    Deadband = 0.0f,
    KeepAlive = 1000            // ms
};
subscription = (Subscription)server.CreateSubscription(state);

Item[] items = new Item[]
{
    new Item(new ItemIdentifier("S7_Program::DB1::Tag1"), true, 0),
    new Item(new ItemIdentifier("S7_Program::DB1::Tag2"), true, 0)
};
subscription.AddItems(items);
subscription.DataChanged += OnDataChanged;

// Handler signature
private static void OnDataChanged(object sender, DataChangedEventArgs e)
{
    foreach (ItemValueResult iv in e.Values)
        Console.WriteLine($"Change: {iv.ItemName} = {iv.Value} @ {iv.Timestamp}");
}

4.5 Write a Value

ItemValue itemValue = new ItemValue
{
    ItemName = "S7_Program::DB1::Tag1",
    Value = 1234
};
IdentifiedResult[] writeResult = server.Write(new ItemValue[] { itemValue });
// writeResult[0].ResultId.Succeeded == true on success
Tag naming: Inside WinCC, internal tag names are TagPrefix::TagName (e.g. S7_Program::DB1::Motor_Speed). External tags configured in the WinCC Tag Management appear with their configured name. Always verify the exact name via OPC browsing before hardcoding.

5. Method 2 - Connectivity Pack / DataMonitor (OLE DB)

The WinCC Connectivity Pack (license 6AV6371-1DR07-... or as part of DataMonitor) exposes the runtime archive, alarm log, and tag table through an OLE DB provider accessible to any ADO.NET consumer.

5.1 Connection String

Provider=WinCCOLEDBProvider.1;
Catalog=CC_Engineering_15_08_19_12_00_00;
Data Source=192.168.2.252\WinCC

The Catalog is the WinCC project name; Data Source is the SQL Server instance created during WinCC install (default \WinCC).

5.2 Read Archived Process Values

using (OleDbConnection conn = new OleDbConnection(connString))
{
    conn.Open();
    string sql = @"SELECT * FROM TAG:R,'S7_Program::DB1::Motor_Speed','0000-00-00 00:10:00.000','0000-00-00 00:11:00.000'";
    using (OleDbCommand cmd = new OleDbCommand(sql, conn))
    using (OleDbDataReader dr = cmd.ExecuteReader())
    {
        while (dr.Read())
            Console.WriteLine($"{dr["Timestamp"]} {dr["RealValue"]}");
    }
}

Read the official WinCC Connectivity Pack manual for the full SQL-like syntax: Siemens Entry ID 102628683 - WinCC Connectivity Pack documentation.

6. Method 3 - Industrial Data Bridge (IDB)

IDB is a Windows service shipped with WinCC that can mirror tags from any OPC DA / OPC UA source (including OPCServer.WinCC) into SQL Server, Oracle, MySQL, SAP RFC, or a text file - with no custom code. The agent is configured through the IDB Configurator GUI on the WinCC station.

Official Siemens entry for IDB: Entry ID 73968374 - WinCC Industrial Data Bridge. Licensing is per station via the Automation License Manager (ALM).

When to choose IDB over a C# client:

  • No C# developer is available on the IT side.
  • Tag list is stable and small (< 5000 tags).
  • You need guaranteed-store-and-forward behaviour during network outages.

7. Method 4 - VBScript with ADODB (no external C# app)

If the integration target is just a SQL table and there is no need for an external C# application, a WinCC Global Script can perform the writes. In the WinCC Graphics Designer, add a Global Action running every N seconds:

Dim conn, rs, sql
Set conn = CreateObject("ADODB.Connection")
conn.Provider = "SQLOLEDB"
conn.Properties("Data Source").Value = "192.168.2.20\SQLEXPRESS"
conn.Properties("Initial Catalog").Value = "PlantHistorian"
conn.Properties("User ID").Value = "sa"
conn.Properties("Password").Value = "secret"
conn.Open
sql = "INSERT INTO TagLog(TagName, Value, TS) VALUES('Motor_Speed', " & _
      HMIRuntime.Tags("Motor_Speed").Read & ", GETDATE())"
conn.Execute(sql)
conn.Close
Set conn = Nothing
Cycle time: 1-second VBS triggers consume measurable CPU on the WinCC server. Use 5-30 second intervals for non-critical mirroring. For sub-second updates, use the OPC path in Section 4 instead.

8. SQL Server Integration from the C# Host

Once the C# app is reading from WinCC, persist values to SQL Server with System.Data.SqlClient or Microsoft.Data.SqlClient.

using (var sql = new SqlConnection("Server=192.168.2.20\\SQLEXPRESS;Database=PlantHistorian;Integrated Security=SSPI;"))
{
    sql.Open();
    using (var cmd = new SqlCommand("INSERT INTO dbo.TagLog (TagName, Value, TS) VALUES (@n, @v, @t)", sql))
    {
        cmd.Parameters.AddWithValue("@n", iv.ItemName);
        cmd.Parameters.AddWithValue("@v", iv.Value);
        cmd.Parameters.AddWithValue("@t", iv.Timestamp);
        cmd.ExecuteNonQuery();
    }
}

For high-throughput applications, batch the inserts and use SqlBulkCopy:

DataTable dt = new DataTable();
dt.Columns.Add("TagName", typeof(string));
dt.Columns.Add("Value", typeof(object));
dt.Columns.Add("TS", typeof(DateTime));
// fill dt...
using (var bulk = new SqlBulkCopy(sql))
{
    bulk.DestinationTableName = "dbo.TagLog";
    bulk.WriteToServer(dt);
}

9. DCOM Configuration (Required for Network OPC)

The single most common cause of Access Denied when a C# app calls opcda://<remote>/OPCServer.WinCC is incomplete DCOM configuration. Apply the following on both the WinCC station and the C# client station.

  1. Create a Windows user (e.g. opcuser) on both machines with identical password. Add it to the local Distributed COM Users group and to Administrators on the WinCC station.
  2. Run WinCC Runtime as that user: Start > WinCC > Autostart > Configure, or in services.msc change the logon of CCEServer, SIMATIC WinCC OPC Server, and SQL Server (WINCC) to opcuser.
  3. Open dcomcnfgComponent Services > Computers > My Computer > DCOM Config.
  4. Right-click OPCServer.WinCCProperties:
    • General tab → Authentication Level: None (test lab) or Connect (production).
    • Location tab → enable Run application on the following computer only.
    • Security tab → customize all three sections and grant opcuser full access.
    • Identity tab → set This user and enter opcuser and the password.
  5. In My Computer properties (top of the DCOM tree):
    • Default Authentication Level: Connect.
    • Default Impersonation Level: Identify.
  6. Open Windows Firewall with Advanced Security and create inbound rules for C:\Windows\System32\dllhost.exe (DCOM launcher) and OPCServer.WinCC.exe on ports 135 (TCP) plus the dynamic RPC range.
  7. Add the WinCC host's IP and the C# host's IP to Trusted Hosts in the registry only when using classic-impersonation (rare).
Verification tool: From the C# client station, run dcomcnfg → right-click My ComputerPropertiesDefault Properties tab. Toggle Enable Distributed COM on this computer. This forces a re-registration of DCOM listeners. Alternatively, use the OpcEnum tool shipped with the OPC Core Components to confirm the remote server is visible.

10. Configuration Reference Table

Parameter Recommended Value Notes
WinCC OPC Server ProgID OPCServer.WinCC Same for V7.2 to V7.5
OPC Specification DA 3.0 (DA 2.0 also works) DA 1.0 lacks subscription
Update Rate 250-1000 ms Below 100 ms increases CPU
KeepAlive 1000 ms Detects dead subscriptions
Deadband 0 (analog) or % of span Filters noise on float tags
DCOM Auth Level Connect None acceptable only in test lab
Impersonation Level Identify Impersonate if write-back required
SQL TCP Port 1433 Use named instances + browser if non-default
SQL Auth Windows integrated (preferred) Use SQL login only if domain trust exists

11. Troubleshooting Matrix

Symptom Hex Code Likely Cause Action
Access Denied on connect 0x80070005 DCOM user mismatch, ACL on OPCServer.WinCC Reapply Section 9; verify identical user/password both sides
Class not registered 0x80040154 OPC server not running, firewall blocked Check WinCC service; open port 135 + RPC range
RPC server unavailable 0x800706BA DCOM disabled, network unreachable Enable DCOM on both; ping by hostname, not IP
Server not reachable on localhost but works on LAN IP - WinCC OPC binds only to NIC Restart CCEServer after network change
Reads return Bad / quality = BadCommFailure 0x80004005 PLC connection down, wrong tag prefix Check WinCC Channel Diagnostics
Subscription stops after 30 minutes - DCOM session timeout Set KeepAlive < session timeout in component services
SQL login fails from WinCC station - Named-pipes disabled, wrong instance Enable TCP in SQL Configuration Manager; test with SSMS
DataMonitor web page blank - IIS not installed / licensed Reinstall DataMonitor; check ALM license

12. Verification Procedure

  1. On the WinCC station, launch Start > Programs > Siemens Automation > SIMATIC > WinCC > OPC and start the OPC Scout. Add the local OPCServer.WinCC, browse to a known tag, drag it into the view, and confirm the value updates.
  2. From the C# client station, run OpcEnum (or OPC Foundation's SampleClient) and add the remote opcda://<WinCC>/OPCServer.WinCC. A successful add confirms DCOM works.
  3. Start the C# application, verify it logs Connect: ok for every tag and that DataChanged fires at the expected UpdateRate.
  4. Confirm rows appear in the target SQL table: SELECT TOP 10 * FROM dbo.TagLog ORDER BY TS DESC;
  5. Pull the network cable between the WinCC station and the C# host. After the configured KeepAlive timeout, the client should log Server not connected. Reconnect the cable; subscription should auto-recover without restarting the C# app.

13. Security and Production Hardening

  • Never leave Authentication Level = None on a production network - it disables RPC packet signing and allows trivial MITM attacks.
  • Use a dedicated opcuser account with no interactive login rights.
  • Restrict the SQL login to the db_datawriter role on the historian database only.
  • Encrypt traffic: OPC UA is supported in WinCC V7.3+ via the OPC UA Server option. Migrate from DA to UA when the C# stack supports it - no DCOM configuration is required.
  • Audit firewall rules annually; Windows updates sometimes reset DCOM defaults.

14. Frequently Asked Questions

Do I need a separate software to connect WinCC to C#?

No. The WinCC OPC DA Server is built into every WinCC Runtime install - no extra license is required. You only need a free .NET OPC API library (OpcNetApi or the OPC Foundation .NET Standard wrappers) on the C# side, plus correctly configured DCOM. Connectivity Pack or Industrial Data Bridge are only required if you want historical archive access or managed tag bridging without writing C# code.

Why do I get Access Denied (0x80070005) when connecting from a remote C# app to opcda://192.168.2.252/OPCServer.WinCC?

The WinCC OPC server and the C# client must use Windows accounts with the same username and password. Verify that opcuser (or whichever account the WinCC services run under) exists on both machines, is in the local Distributed COM Users group, and that DCOM launch/access permissions on the OPCServer.WinCC COM object allow that account. See Section 9 for the full checklist.

Can a C# program write values back to WinCC via OPC DA?

Yes. The OPC DA 3.0 specification allows client writes; call Opc.Da.Server.Write with an ItemValue array and check the IdentifiedResult.ResultId for each tag. Set DCOM Impersonation Level to Impersonate if writes return 0x80070005 while reads succeed.

What is the difference between Connectivity Pack, DataMonitor, and Industrial Data Bridge?

Connectivity Pack provides OLE DB, SOAP, OPC XML, and OPC UA access to the WinCC archive for read/aggregation. DataMonitor is an Information Server add-on with web-based reports and the same OLE DB plumbing. Industrial Data Bridge (IDB) is a declarative, code-free tag-to-database mirror (SQL, Oracle, MySQL, SAP, text) configured through a GUI. IDB is best when you have many tags and no C# developer; Connectivity Pack is best for analytical/BI queries on historical data.

Can I avoid DCOM entirely and use OPC UA instead?

Yes, on WinCC V7.3 and later. Enable the OPC UA Server option in the WinCC project properties and add the Windows certificate to the trusted peers of the C# client. OPC UA runs over TCP port 4840, requires no DCOM, and is the recommended path for new deployments. See Siemens support entry 109769510 - WinCC OPC UA configuration.

How fast can a C# app poll WinCC tags over OPC DA?

With a 100 ms UpdateRate on a dedicated Windows 10/11 station, a 500-tag subscription runs comfortably at < 50 ms round-trip per read. The bottleneck is typically the WinCC channel driver, not the OPC layer. For sub-100 ms cycle times, use direct S7 communication via the S7 protocol in the C# app or move to OPC UA at 50-200 ms.

Back to blog