Reading WinCC Project Version at Runtime: C and VBS Scripts

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

Reading the WinCC Project Version at Runtime with C and VBS Scripts

Every Siemens WinCC V7.x project carries a version identifier in its Configuration Studio (CS) metadata, but that value is normally only visible in WinCC Explorer, not in runtime. Engineers frequently need to expose the running project version to the HMI faceplate, the alarm log, an audit trail, or a conditional graphics script so that maintenance staff can immediately confirm which revision of the project is loaded on a station or a server. This reference documents the supported way to read MCPTPROJECT.PROJECTVERSION from runtime using a WinCC C-script, the alternative routes using VBS and WinCC internal tags, and the commissioning steps to wire the result into a faceplate or archive.

Scope: The C-script solution below targets WinCC V7.0 SP3 through V7.5 SP2, where the CS database is stored as a local Microsoft Access file and is accessible via ODBC/DSN. WinCC Professional (TIA Portal) and WinCC Unified use different scripting models and are addressed briefly in the comparison section.

1. Prerequisites

  • WinCC V7.0 SP3 or later, running on Windows 7 SP1 / Windows Server 2008 R2 or newer.
  • Local administrator rights on the engineering station to configure the project version in the project properties dialog.
  • The WinCC project must be opened at least once in WinCC Explorer so that the CS database is created and the DSN is registered.
  • Global Scripting rights in the WinCC user administration for the user that will run the script (typically Administrator or a custom role with Runtime - Start/Stop rights).
  • For the C-script path, Microsoft OLE DB / ODBC drivers for Access (ACE.OLEDB.12.0 or Microsoft.Jet.OLEDB.4.0) must be present. Windows 10 / Server 2016+ ships the 64-bit ACE driver; 32-bit WinCC still requires the 32-bit ACE redistributable.

2. WinCC Project Version Field: Where It Lives

Open WinCC Explorer, right-click the project node, and choose Properties. The dialog exposes a Version field (in some builds labelled Project version or Project revision). Whatever string is entered there is written to the PROJECTVERSION column of the MCPTPROJECT table in the project's CS database when the project is saved or compiled.

The CS database is created automatically at <ProjectPath>\<ProjectName>.mdf for SQL Server backed projects, or <ProjectPath>\<ProjectName>.MDB for the default Access file. A system DSN with the same name as the project is registered during project activation; this DSN is the handle used by the script.

3. The MCPTPROJECT Table Layout

Column Index (0-based) Field Name (approx.) Content
0 PROJECTNAME WinCC project name
1 PROJECTPATH Full filesystem path of the .MCP
2 PROJECTVERSION Free-form version string entered in project properties
3+ CREATIONDATETIME, COMPUTERNAME, … Project creation metadata

Because column order can change between WinCC service packs, the production code shown below uses the field name rather than the index. The original posting from the WinCC community used index 2 (the third field) on WinCC V7.0 SP3. If you upgrade, verify with Microsoft Access or a quick SELECT that PROJECTVERSION is still column index 2 or switch to a named lookup.

4. C-Script: Production-Ready Implementation

The following function returns the project version as a char*. It is the same approach the community posted, hardened with explicit error handling, named field access, and safe buffer sizes.

//----------------------------------------------------------------------
// Filename: DetermineVersionNumber.fct
// Purpose : Return the WinCC project version string from the CS DB.
// Caller  : Trigger on project open or store result in internal tag.
// Tested  : WinCC V7.4 SP1, V7.5 SP2 (32-bit project)
//----------------------------------------------------------------------
#include "apdefap.h"
#include "apdb.h"   // ADODB wrapper, optional

// ODK prototypes (also in DMdef.h, supplied with WinCC ODK)
extern "C" {
  BOOL DMGetRuntimeProjectA(LPSTR szProjectName, DWORD dwSize, CMN_ERRORA* lpError);
  BOOL DMGetProjectInformationA(LPSTR szProjectName, DM_PROJECT_INFO* lpInfo, CMN_ERRORA* lpError);
}

char* DetermineVersionNumber()
{
    static char szVersion[256];           // static so caller can read after return
    char  szProject[256] = {0};
    char  szConn[512]    = {0};
    char  szQuery[256]   = {0};
    CMN_ERRORA err       = {0};
    DM_PROJECT_INFO info = {0};

    memset(szVersion, 0, sizeof(szVersion));

    // ---- Step 1: get the runtime project name and its DSN
    if (!DMGetRuntimeProjectA(szProject, sizeof(szProject), &err)) {
        printf("DMGetRuntimeProjectA failed (0x%08X)\r\n", err.dwError1);
        return szVersion;
    }
    if (!DMGetProjectInformationA(szProject, &info, &err)) {
        printf("DMGetProjectInformationA failed (0x%08X)\r\n", err.dwError1);
        return szVersion;
    }

    sprintf(szConn,  "DSN=%s;", info.szDSNName);
    sprintf(szQuery, "SELECT PROJECTVERSION FROM MCPTPROJECT");

    // ---- Step 2: open the CS database through ADODB
    __object* con = __object_create("ADODB.Connection");
    __object* rs  = __object_create("ADODB.RecordSet");

    con->Open(szConn);
    if (con->State == 0) {
        printf("DB connection failed for DSN=%s\r\n", info.szDSNName);
        __object_delete(rs);
        __object_delete(con);
        return szVersion;
    }

    rs->Open(szQuery, con, 1);            // adOpenKeyset = 1
    if (!rs->EOF) {
        // Use the named field to be robust against column re-ordering.
        strncpy(szVersion, (const char*)rs->Fields("PROJECTVERSION"),
                sizeof(szVersion) - 1);
    }
    rs->Close();
    con->Close();

    __object_delete(rs);
    __object_delete(con);
    return szVersion;
}

4.1 Wiring the C-Script into the Project

  1. Open the WinCC project and choose Global Scripts → C-Editor.
  2. Create a new function, paste the code above, and save as DetermineVersionNumber.fct.
  3. Create a standard function (no return value) named e.g. Init_ProjectVersion that calls DetermineVersionNumber() and writes the result to an internal text tag.
  4. Open Project Properties → Startup and add the function to the Global Script Runtime - On Project Start actions list so the tag is populated before the first picture is loaded.

4.2 Why an Internal Tag, Not a Direct Call

Calling a C-function from every picture is expensive and triggers the ADODB round trip each time. By storing the result in a 256-byte internal text tag once at startup, every faceplate, alarm, and VBS action can read it in microseconds with GetTagChar("@ProjectVersion"). The internal tag also makes the value visible to the WinCC tag simulator and to the Tag Logging archive, which is useful when the audit trail must record which project version triggered an event.

5. VBScript Alternatives

VBS in WinCC runtime does not expose DMGetRuntimeProjectA directly. Three practical routes exist, in order of robustness.

5.1 Read the Internal Tag Populated by the C-Script

' VBS in a button or faceplate
Dim sVer
sVer = HMIRuntime.Tags("@ProjectVersion").Read
HMIRuntime.Trace "Project version is: " & sVer & vbCrLf

This is the recommended pattern. The C-script does the database work once; VBS only reads a tag, so the same value is available everywhere from any picture.

5.2 Use the Internal Tag DatasourceNameRT

WinCC exposes the runtime DSN name as an internal tag. Combined with a stored procedure or a pre-built query it can be used to derive the project name, but it does not directly contain the version, so this is only useful when the project version is appended to the DSN (a common deployment convention).

Dim sDSN
sDSN = HMIRuntime.Tags("DatasourceNameRT").Read   ' e.g. "MyProject_V3_2_1"
HMIRuntime.Trace "Runtime DSN: " & sDSN & vbCrLf

5.3 Direct ADODB from VBS

VBS in WinCC has full access to ADODB.Connection via the global CreateObject equivalent. You can therefore perform the same query as the C-script, with the caveat that VBS error handling is lighter and there is no static buffer:

' VBS action - call once at startup
Function GetProjectVersion()
    Dim sVer, sDSN, sConn
    On Error Resume Next

    ' The DSN equals the project name; retrieve it from the WinCC API.
    sDSN = HMIRuntime.Tags("DatasourceNameRT").Read
    sConn = "DSN=" & sDSN & ";"

    Dim con, rs
    Set con = CreateObject("ADODB.Connection")
    con.Open sConn
    If con.State = 0 Then
        HMIRuntime.Trace "VBS: DB connection failed" & vbCrLf
        GetProjectVersion = ""
        Exit Function
    End If

    Set rs = con.Execute("SELECT PROJECTVERSION FROM MCPTPROJECT")
    If Not rs.EOF Then sVer = rs.Fields("PROJECTVERSION").Value
    rs.Close : con.Close
    Set rs = Nothing : Set con = Nothing

    GetProjectVersion = sVer
End Function

' Write the result into the internal tag
HMIRuntime.Tags("@ProjectVersion").Write GetProjectVersion()
Note: The DatasourceNameRT internal tag is supplied automatically by WinCC; you do not need to declare it manually. If you do not see it in the tag list, check that the project has been activated at least once and that the internal tag group System is visible.

6. Configuring the Project Version Property

The script is only as good as the data the engineer types in. A disciplined versioning scheme prevents mystery values such as final, latest, or an empty string appearing in the field.

  • Use a three-part semantic version, e.g. 2.4.1, optionally suffixed with a build counter: 2.4.1+build-2025-04-12.
  • Restrict the dialog field to a regex via a WinCC change-control procedure; the WinCC UI itself does not validate the string.
  • Reproduce the value in the file name of the .MC archive, in the ESD file name, and on the cabinet label so field staff can match the project to the HMI.
  • Update the version before the first compile on a new revision; re-compiling does not retroactively update the field if the dialog is closed without saving.

7. Exposing the Version to Operators

A common requirement is to print the version on the System Info picture so that the operator can quote it during a service call. To do this:

  1. Create the internal text tag @ProjectVersion with length 256 in the Internal tags group.
  2. Add an I/O field or a static text element to the system picture and link its Output Value property to @ProjectVersion.
  3. Optionally append a Configuration property that triggers a tag logging entry whenever the tag changes, so the version change is captured the first time the new project is started.

8. Verification Steps

  1. Open the WinCC project, enter TEST-1.0.0 in Project Properties → Version, and save.
  2. Compile the project and start runtime.
  3. Open Global Script → Debug and confirm the GSC Diagnostics window prints the version string without the DB connection failed line.
  4. In the system picture, the I/O field bound to @ProjectVersion should display TEST-1.0.0.
  5. Close runtime, change the version to TEST-1.0.1, recompile, restart runtime, and confirm the displayed value updates without restarting the OS or the WinCC service.
  6. Inspect the project.MDB file directly with Microsoft Access and verify the MCPTPROJECT.PROJECTVERSION row matches the value displayed in runtime.

9. Troubleshooting Matrix

Symptom Likely Cause Fix
DB Connection Failed printed in GSC Diagnostics DSN not registered, or 32-bit/64-bit driver mismatch Activate the project once so the DSN is created. Install the matching bitness of ACE.OLEDB.12.0 (32-bit WinCC = 32-bit driver).
Empty string returned even though the project property is filled Column index changed after a service pack upgrade Switch the SELECT to use the named field PROJECTVERSION instead of Fields(2).
Function compiles but is never called Function not added to the On Project Start actions list Open Project Properties → Startup → Global Script Runtime and add the function; re-activate the project.
Value visible in C-debug but VBS returns empty Internal tag has the wrong type (binary/text) or wrong length Declare the tag as Text tag, 16-bit character set, length 256.
DMGetRuntimeProjectA failed 0x80040E14 WinCC ODK runtime not initialized Ensure DMClient.dll is registered with regsvr32 on the runtime station. Confirm the ODK runtime option is installed.
Script returns the value of the wrong project on a redundant pair DSN on the partner server points to a different project folder Check the project path in Project Properties → General on both servers and replicate the project folder before redundancy switch.
Error 2147467259 (80004005) when opening the MDB Access denied, file is read-only, or path contains spaces and is not quoted Grant the WinCC runtime user modify rights on the project folder; avoid spaces in the project path or quote the DSN value.

10. Cross-Platform Notes

Platform Recommended Path Comments
WinCC V7.0 SP3 to V7.5 SP2 C-script with ADODB, internal tag, VBS reads tag Default Access CS database. Code in this article applies directly.
WinCC V7.4 SP1 with SQL Server CS Same C-script, change connection string to Provider=SQLNCLI11;Server=...;Database=<CS>;Trusted_Connection=Yes Used for multi-user engineering.
WinCC Professional (TIA Portal V15-V18) Use SWB → Project Information → Project Version read via HMIRuntime.SysFct.GetProjectInformation or expose the value through a configured tag No direct DB access; the version is exposed by the HMI runtime API.
WinCC Unified (V16+) JavaScript: HMIRuntime.RuntimeFunctions.GetProjectVersion() or read a configured tag No ADODB, no C-scripts. VBS not available.

11. Performance and Security Considerations

The CS database is opened on a local ODBC DSN, so the round trip is on the order of 1-5 ms on a modern Windows station, but the cost grows if the DSN points across a network. The startup-time cost is negligible, but calling the C-function from a frequently fired cyclic action (e.g. 100 ms) will consume one connection per call and will eventually fail when the connection pool is exhausted. Always read the cached internal tag from cyclic actions.

Restrict read access to the CS database folder. The .MDB contains every project property, including paths, user names, and any value placed in the project notes. If the project has proprietary tag names, lock the file with NTFS ACLs. For SQL-backed CS, the db_owner role on the CS database is sufficient for the script; do not grant sysadmin to the runtime account.

12. Frequently Asked Questions

Does the version field update automatically when I edit the project?

No. WinCC writes the value of the Project Properties → Version field to the MCPTPROJECT table when the project is saved or compiled, but the field itself is not auto-incremented. The engineer must update it before each compile cycle; a one-line change-management SOP that forces a version bump before every release prevents stale values.

Why does the C-script return an empty string on the first runtime start?

Two common causes: (1) the DSN was not registered yet because the project has never been activated, or (2) the column index changed in a newer service pack. Open the project.MDB with Microsoft Access, look at the MCPTPROJECT table, and confirm that the third column is still labelled PROJECTVERSION. Switch to the named field Fields("PROJECTVERSION") for long-term robustness.

Can I read the project version from a WinCC Unified faceplate?

Yes. WinCC Unified exposes a JavaScript runtime API. Use HMIRuntime.RuntimeFunctions.GetProjectVersion() on a screen load event, or read a pre-configured internal tag that you populate via a startup script. ADODB and the C-script path are not available in Unified.

Is there a way to log the project version automatically at runtime start?

Yes. In the C-script On Project Start action, after writing the value to @ProjectVersion, also call UserArchiveWrite or simply append a comment line to an alarm message via MSRTSetCommentA. Combined with Tag Logging's Comment field, this gives a permanent audit trail of which project revision was running when an event occurred.

What happens on a redundant WinCC server pair if the version is changed on only one side?

When the standby server takes over, its CS database determines the value, so a half-updated pair will alternate between the two versions during failover. Replicate the .MCP and the .MDB together as a single unit, and verify with the Redundancy Control diagnostics that both partners report the same value after the change has been deployed.

Back to blog