Validating File and Folder Names in WinCC Unified VBScript

David Krause13 min read
HMI / SCADASiemensTutorial / How-to
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 Unified scripting on Unified Comfort Panels and on PC Runtime gives the operator an I/O field that can collect a folder or file name, but the runtime has no built-in IsValidWindowsFileName function. The system is fully responsible for enforcing the Windows naming rules: a bad character in the name, a reserved device name, a trailing period, or a path longer than 260 characters will either be rejected silently by the operating system or, worse, create a file the operator cannot address. This reference documents a defensive VBScript validator, a try/catch pattern around the FileSystemObject, an equivalent JavaScript implementation, the path-length constraints, and the step-by-step wiring on a Unified screen.

Two strategies are valid and usually combined. The first runs on the operator's keystroke and gives immediate feedback, so the operator fixes the entry before pressing Save. The second wraps the actual filesystem call and catches anything the validator missed, including network-share errors and case collisions on SMB mounts.

Prerequisites

  • TIA Portal V17 Update 4 or later; TIA Portal V18 for new projects.
  • WinCC Unified V17 or V18 engineering and runtime installed.
  • Unified Comfort Panel: MTP700, MTP1000, MTP1200, MTP1500, MTP1900, MTP2200 with image V17.0.0.18 or later, or PC Runtime V17/V18.
  • JavaScript engine on the runtime requires image V16.4 or later (VBS is available from V16.0).
  • Scripting licensed on the HMI device. The WinCC Unified Scripting license is part of the standard runtime license; confirm under Runtime Settings > Services > Scripting.
  • A project tag of type WString bound to the I/O field that collects the name.

Windows File and Folder Naming Rules

The validator must enforce the same rules that the Windows file system enforces. The authoritative source is the Microsoft Naming Files, Paths, and Namespaces article, which lists every reserved character and every reserved device name. The constraints the VBS function below covers are summarized here:

Rule Detail
Reserved characters < > : " / \ | ? * plus control characters 0x00 through 0x1F
Reserved device names CON, PRN, AUX, NUL, COM1 through COM9, LPT1 through LPT9, with or without an extension
Trailing characters No trailing space and no trailing period on the final component
Length Each name component ≤ 255 characters; full path ≤ 260 characters unless long paths are enabled
Empty input Empty string is invalid; whitespace-only is invalid
Reserved-only names A name that consists entirely of dots (e.g. .., ...) is invalid
These rules apply to the file system on which the runtime writes. Unified Comfort Panels run a Windows 10 IoT Enterprise base, so the rules above apply directly. If the panel writes to a Linux-mounted SMB share (Synology, QNAP, Ubuntu Samba), the share is case-sensitive and additionally rejects names that match existing names in different case. Add an existence check before the write.

Script Placement and Architecture

Bind the validator to one of three locations, ordered by how early you want to reject the input:

  1. On the I/O field "Changed" event: rejects the value and shows an inline message. Best for guiding the operator live.
  2. On a button "Click" event: rejects the value when the operator presses Save or Create. Best for forms that need the full string for one validation pass.
  3. On a custom function in the project scripts: a shared function that both event handlers call, so the rules exist in one place.

Create a project-wide VBScript module called FileNameValidation under Scripts > VBScripts in the TIA Portal project tree. Add a function IsValidWinName and a function TryCreateFolder. Reference both from the screen events that accept a name.

VBScript Validation Function

Paste the function below into the FileNameValidation module. The function returns True for a valid name and False for an invalid one, with a human-readable reason written to the second argument.

' Returns True if sValue is a valid Windows file or folder name component.
' sReason is populated on failure.
Function IsValidWinName(ByVal sValue, ByRef sReason)
    Dim i, j, sChar, sName, sBase, bOnlyDots
    Dim arrReserved
    sReason = ""
    sName = Trim(sValue)

    If Len(sName) = 0 Then
        sReason = "Name is empty."
        IsValidWinName = False
        Exit Function
    End If

    If Len(sName) > 255 Then
        sReason = "Name exceeds 255 characters."
        IsValidWinName = False
        Exit Function
    End If

    If Right(sName, 1) = " " Or Right(sName, 1) = "." Then
        sReason = "Name must not end with space or period."
        IsValidWinName = False
        Exit Function
    End If

    ' Reserved device names, with or without extension.
    If InStr(sName, ".") > 0 Then
        sBase = UCase(Left(sName, InStr(sName, ".") - 1))
    Else
        sBase = UCase(sName)
    End If
    arrReserved = Array("CON","PRN","AUX","NUL", _
                        "COM1","COM2","COM3","COM4","COM5", _
                        "COM6","COM7","COM8","COM9", _
                        "LPT1","LPT2","LPT3","LPT4","LPT5", _
                        "LPT6","LPT7","LPT8","LPT9")
    For i = 0 To UBound(arrReserved)
        If sBase = arrReserved(i) Then
            sReason = "Name is a reserved device name (" & sBase & ")."
            IsValidWinName = False
            Exit Function
        End If
    Next

    ' Reserved characters and control characters.
    For i = 1 To Len(sName)
        sChar = Mid(sName, i, 1)
        Select Case sChar
            Case "<", ">", ":", """", "/", "\", "|", "?", "*"
                sReason = "Name contains reserved character '" & sChar & "'."
                IsValidWinName = False
                Exit Function
        End Select
        If Asc(sChar) < 32 Then
            sReason = "Name contains a control character."
            IsValidWinName = False
            Exit Function
        End If
    Next

    ' Name consisting only of dots.
    bOnlyDots = True
    For j = 1 To Len(sName)
        If Mid(sName, j, 1) <> "." Then
            bOnlyDots = False
            Exit For
        End If
    Next
    If bOnlyDots Then
        sReason = "Name must not consist only of dots."
        IsValidWinName = False
        Exit Function
    End If

    IsValidWinName = True
End Function

Call the function from an I/O field's "Changed" event so the operator sees the failure reason as they type:

Dim sReason, bOK
bOK = IsValidWinName(SmartTag("FolderName"), sReason)
If Not bOK Then
    ShowSystemAlarm("Invalid name: " & sReason)
Else
    ShowSystemAlarm("Name is valid.")
End If
Operator types name Trim and length check Reserved device name Reserved char / control Trailing space or dot Accept, return True Reject, return False ShowSystemAlarm(sReason)

Try-Catch Validation with FileSystemObject

The validator above does not check that the path is reachable, that the share is online, or that the runtime user has write permission. Wrap the actual write in a try/catch-equivalent that uses the VBScript Err object. WinCC Unified exposes the FileSystemObject through CreateObject on both Unified Comfort Panels and PC Runtime.

Function TryCreateFolder(ByVal sFullPath, ByRef sErrMsg)
    Dim oFSO
    On Error Resume Next
    Set oFSO = CreateObject("Scripting.FileSystemObject")
    If Err.Number <> 0 Then
        sErrMsg = "FSO unavailable: 0x" & Hex(Err.Number)
        TryCreateFolder = False
        Exit Function
    End If

    If oFSO.FolderExists(sFullPath) Then
        sErrMsg = "Folder already exists."
        TryCreateFolder = False
        Exit Function
    End If

    oFSO.CreateFolder sFullPath
    If Err.Number <> 0 Then
        sErrMsg = "CreateFolder failed: 0x" & Hex(Err.Number) & " " & Err.Description
        TryCreateFolder = False
    Else
        sErrMsg = ""
        TryCreateFolder = True
    End If
    On Error Goto 0
End Function
The VBScript engine on Unified Comfort Panels does not raise structured exceptions. The Err object is the only error signal. Always set On Error Goto 0 after the FSO call so unrelated runtime errors are not silently suppressed.

Common HRESULT values returned through Err.Number from the FileSystemObject:

Hex Decimal Meaning
0x800A0046 32774 Permission denied
0x800A0035 52 File not found
0x800A0034 52 File already exists
0x800A004C 76 Path not found

JavaScript RegExp Implementation

The VBS engine on WinCC Unified does not expose the Windows Script Host VBScript.RegExp object by default, so the function above uses InStr, Mid, and a Select Case scan. If your faceplates already use JavaScript, the RegExp object is built into the JavaScript engine and the equivalent validator is shorter:

// Project script, exported as IsValidWinName(sValue)
export function IsValidWinName(sValue) {
    if (typeof sValue !== 'string') return { ok: false, reason: 'Not a string' };
    const reserved = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\..*)?$/i;
    const badChar  = /[<>:"\/\\|?*\x00-\x1F]/;
    const name = sValue.trim();
    if (name.length === 0)    return { ok: false, reason: 'Empty' };
    if (name.length > 255)    return { ok: false, reason: 'Longer than 255 characters' };
    if (/^[. ]+$/.test(name)) return { ok: false, reason: 'Only dots or spaces' };
    if (/[. ]$/.test(name))   return { ok: false, reason: 'Trailing space or period' };
    if (badChar.test(name))   return { ok: false, reason: 'Reserved character' };
    if (reserved.test(name))  return { ok: false, reason: 'Reserved device name' };
    return { ok: true, reason: '' };
}

Call the JavaScript function from a script module bound to a screen event, the same way the VBS function is called. Return the reason string to the operator through a String tag bound to an output field, or raise a system alarm with HMIRuntime.Alarm from the JavaScript context.

The functions above validate only the file or folder name component. To validate a complete path, split the string on \ and /, run the component check on each segment, and verify the root segment matches ^[A-Z]:$ or starts with \\\\ for a UNC path.

Path Length, Long Paths, and Case-Sensitive Shares

The Win32 API uses MAX_PATH = 260 characters by default. The Unified scripting engine calls the same Win32 APIs, so a full path longer than 260 characters returns error 0x800A004C (path not found) even when every name component is valid. Long path support is enabled through the registry on the runtime image:

  1. Open the registry on the runtime PC or panel image: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem.
  2. Set LongPathsEnabled (DWORD) to 1.
  3. Reboot the runtime.

On Unified Comfort Panels, the registry can be reached through the Siemens Image Configuration tool. The Microsoft Maximum Path Length Limitation article documents the LongPathsEnabled key. Validate the full path length in the script before the call to fail fast:

If Len(sFullPath) > 260 Then
    sReason = "Path exceeds 260 characters; long paths are not enabled on this runtime."
End If

Windows is case-insensitive by default, but a Unified panel that exports to a Linux SMB share hits a case-sensitive file system. The Windows rules above do not check for case collisions. Add an explicit existence check before the write:

Function IsNameFree(ByVal sDir, ByVal sName)
    Dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")
    Dim sPath : sPath = oFSO.BuildPath(sDir, sName)
    IsNameFree = Not (oFSO.FileExists(sPath) Or oFSO.FolderExists(sPath))
End Function

Step-by-Step Implementation

  1. Open the TIA Portal project, select the HMI device, and add a new VBScript module under Scripts > VBScripts called FileNameValidation.
  2. Paste the IsValidWinName and TryCreateFolder functions from the sections above into the module.
  3. Compile the project (Project > Compile > Software (rebuild all)) to confirm there are no syntax errors. The output window lists each module and the number of errors; expect zero.
  4. Open the screen that hosts the name entry I/O field. Add a "Changed" event on the I/O field and call IsValidWinName against the tag that holds the entry.
  5. On the same screen, add an output field bound to a string tag. In the same Changed event, write the failure reason into that tag so the operator sees the explanation live.
  6. Add a button labeled "Create folder" with a "Click" event. In the Click handler, call IsValidWinName first, then call TryCreateFolder only when validation passes. Show the FSO error message in the output field when the call fails.
  7. Compile and download to the Unified Comfort Panel or PC Runtime.
  8. Open the runtime and intentionally enter the test cases from the verification checklist below. Each must be rejected with the matching reason.
  9. Enter a clean name (e.g. Reports_2025). The validator returns True and the folder is created on the share.

Verification and Troubleshooting

Run the following matrix on the deployed runtime before sign-off. The first block is a positive and negative verification table; the second is a troubleshooting matrix.

Input Expected Reason returned
CON Reject Reserved device name (CON)
CON.txt Reject Reserved device name (CON)
a/b Reject Reserved character '/'
foo:bar Reject Reserved character ':'
foo?bar Reject Reserved character '?'
256 characters Reject Exceeds 255 characters
(two spaces) Reject Name is empty
... Reject Must not consist only of dots
foo (trailing space) Reject Trailing space or period
Reports_2025 Accept (empty)
Symptom Likely cause Fix
Validator returns True but CreateFolder fails Path segment after the typed name contains a reserved character, e.g. an absolute path was typed in Split the full path on \ and validate every segment
Validator returns False for a name that looks clean Trailing space from the I/O field property is preserved Trim the input in the validator (already in the snippet) and also clear the I/O field's "Clear on invalid" property
FSO returns 0x800A004C on a short path Long path disabled and the absolute path includes a long network share prefix Enable LongPathsEnabled on the runtime image, or move the share closer to the root
JavaScript IsValidWinName is not found Function not exported or panel is on image V16.0-V16.3 without the JavaScript engine Update panel image to V16.4 or later; verify the function is exported with export function
Validator passes but file is created in wrong case on SMB share Case-sensitive share Add the IsNameFree check or normalize case before write
Script does not fire on the I/O field Runtime setting "Scripting" disabled or scripting not licensed Enable scripting under Runtime Settings > Services; confirm the HMI license includes the Unified Scripting component
Operator can paste a control character I/O field "Input check" set to "None" Set "Input check" to "Alphanumeric" or write a JavaScript onkeydown handler on the faceplate to drop control characters

Edge Cases and Performance

Edge cases that the simple validator handles correctly but that the operator should be aware of:

  • Unicode in folder names: Windows allows Unicode in file names, including characters from extended code pages. The validator above does not block Unicode, which is correct. If the share does not support Unicode (legacy FAT), reject code points above U+007F at the panel level.
  • Names with leading periods: .gitignore is valid on Windows. The validator allows it. On a Linux share, a leading dot hides the file, which may or may not be the desired behavior. Document this for the operator.
  • Numeric-only names: 12345 is valid. Do not add a "must contain a letter" rule unless the project requires it.
  • Embedded null characters: blocked by the control character check (0x00-0x1F). The I/O field on Unified usually blocks these at input, but a paste from the clipboard can sneak them in.

The VBScript scan is O(n) over the name length, which is bounded at 255. Typical execution is well under 1 ms on a Unified Comfort Panel. Call the validator on the Changed event of the I/O field, not on every screen cycle. The try/catch with FileSystemObject.CreateFolder adds a filesystem roundtrip and a network roundtrip on remote shares; call it once on the Save event, not on every keystroke.

FAQ

Can I use a regular expression in WinCC Unified VBScript?

The VBS engine on WinCC Unified does not expose the Windows Script Host RegExp object by default; you cannot reliably call CreateObject("VBScript.RegExp") from runtime scripts. Use a string scan with InStr, Mid, and Select Case instead, or switch to the JavaScript engine where the RegExp object is built into the language.

Which characters are reserved in a Windows file name?

The reserved set is < > : " / \ | ? * plus control characters 0x00-0x1F. A name may not end with a space or period, may not be empty, and may not be a reserved device name such as CON, PRN, AUX, NUL, COM1 through COM9, or LPT1 through LPT9. The full list is in the Microsoft Naming Files, Paths, and Namespaces article.

Should I validate before the call or use a try-catch on the file system call?

Both. Run the inline validator on the Changed event of the I/O field to give immediate feedback. Run FileSystemObject.CreateFolder wrapped in On Error Resume Next on the Save event so any path or permission error on the share is surfaced with a clear message.

Why does my validator pass but the file system call still fail with "path not found"?

The name component is valid but the full path exceeds 260 characters and the runtime image has long path support disabled. Enable LongPathsEnabled in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem, shorten the share prefix, or check the full path length in the script before the call.

Is FileSystemObject available on a Unified Comfort Panel?

Yes. CreateObject("Scripting.FileSystemObject") is available on Unified Comfort Panels running image V16 or later and on PC Runtime V16 or later. Permission to write the target directory is governed by the runtime user, not the script; configure the share or local folder ACL with the runtime's service account in mind.

Back to blog