Fixing TP700 Comfort SD File Delete Error in TIA Portal V15.1

David Krause15 min read
HMI ProgrammingSiemensTroubleshooting
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

Problem Overview

On a SIMATIC TP700 Comfort panel programmed with TIA Portal V15.1, an HMI script that calls fo.kill (or fso.DeleteFile) to delete .csv archive logs on the SD card returns a runtime error. The most common symptom is an HMI alarm of the form "Permission denied" or "Access is denied" raised against the line that performs the file deletion, while file copy and file move operations against the same path complete successfully. The same script logic usually deletes files from internal flash (\Storage Card MMC\) without complaint, which points the investigation at the SD card subsystem or at the file attributes written by the archiving function.

The typical use case is a rolling retention policy: keep only the last seven daily log files on the SD card and delete the oldest one when a new day begins. Engineers who implement the obvious loop with fo.kill discover that the deletion always fails on the very first iteration, even though the file exists and the path resolves correctly.

This article documents the root cause, three field-proven workarounds, and a complete drop-in script for rolling retention on a TP700 Comfort in TIA Portal V15.1.

Affected products: All TP700 Comfort panels (6AV2 124-1MC01-0AX0 family) running WinCC Comfort/Advanced runtime generated from TIA Portal V15.1, with archive logs stored on the optional SD card. The same behavior is observed on TP900, TP1200, TP1500, TP1900, TP2200 Comfort panels and on the WinCC Runtime Advanced PC runtime because they share the same archive engine and VBScript host.

Root Cause: Read-Only Attribute Set by ArchiveLogFile

The root cause is a Windows-style file attribute, not a missing path or a damaged card. The WinCC Comfort/Advanced ArchiveLogFile system function, when used to close a segmented log segment and write it to the SD card as a stand-alone .csv file, creates the destination file with the Read-Only attribute (DOS attribute 0x01) set. The runtime sets this attribute to protect the file from being mutated by an HMI script while it is still referenced as an active archive segment. Once the segment is closed, the attribute is not automatically cleared.

The file then presents itself to the FileSystemObject (FSO) used by the VBScript host on the HMI as read-only. Both fo.kill and fso.DeleteFile refuse to remove a file that carries the read-only bit, returning error 70 ("Permission denied") or error 5, depending on which method is called.

This explains the precise symptom: file copy (fso.FileCopy) works because copy does not require write permission on the source; file delete fails because delete requires write permission. It also explains why the same deletion succeeds on files written by any method other than ArchiveLogFile (for example, files written by a CSV data log, a script that opens the file with fso.CreateTextFile, or a file copied in from a USB stick).

File creation method Read-only attribute? fo.kill works?
ArchiveLogFile (closed segment) Yes (0x01) No - error 70
CSV data log (continuous) No Yes
fso.CreateTextFile No Yes
fso.FileCopy from another volume No Yes
fso.MoveFile from internal flash No Yes

Why fo.kill Fails on Read-Only Files

The WinCC VBScript host on a Comfort panel exposes two delete primitives:

  • fo.kill PathName - the legacy FileSystemObject shortcut for deletion. It returns no value and raises VBScript error 70 ("Permission denied") if the target file has the read-only bit set.
  • fso.DeleteFile PathName [, Force] - the explicit FSO method. With the optional Force argument set to True, it bypasses the read-only check and deletes the file. Without Force, it also returns error 70.

Because fo.kill is a thin wrapper around the Windows DeleteFile API and the SD card is formatted FAT32, the OS enforces the DOS read-only attribute. Setting fso.DeleteFile PathName, True is the fastest fix, but it is also the most opaque in error handling: if the file does not exist, the call still raises an error and the surrounding On Error Resume Next block masks the failure.

Diagnostic Procedure Before Writing Fix Code

Before changing the script, confirm that the read-only bit is indeed the cause. Use a temporary diagnostic script scheduled to run once, with output sent to a status tag:

  1. On the TP700 Comfort, insert the SD card and confirm the panel recognizes it under Control Panel > Storage Card.
  2. Trigger a manual archive backup from Control Panel > Backup/Restore so at least one closed .csv segment exists under \Storage Card SD\Logs\.
  3. Insert the SD card into a Windows PC and inspect the file properties of the .csv. Verify that the Read-only checkbox is set under Properties > General.
  4. Uncheck Read-only on the PC, save the change, reinsert the SD card into the panel, and run the original fo.kill script. If the file is now deleted, the read-only attribute is confirmed as the root cause.
  5. Also confirm the SD card's physical write-protect slider is in the unlocked position. On full-size SD and SDHC cards, the small slider on the left edge of the card body must be pushed toward the contacts (the "unlocked" position). On microSD cards used with the TP700 adapter, no mechanical lock exists, but the adapter itself carries the same slider and must be inspected.
The TP700 Comfort panel itself cannot toggle the read-only attribute from the system control panel - that dialog exposes only backup, restore, and format functions. The attribute must be cleared by the VBScript runtime, or the file must be re-created by a method that does not set the bit.

Solution 1: Clear the Attribute with fso.SetAttr Before Deleting

The cleanest fix is to clear the read-only attribute with fso.SetAttr and then delete the file. SetAttr takes the attribute value as a numeric bitmask:

Constant Value Meaning
Normal 0 Clear all attribute bits (read/write)
ReadOnly 1 Read-only
Hidden 2 Hidden
System 4 System file
Archive 32 Archive bit (default on FAT32)

Calling fso.SetAttr PathName, 0 strips the read-only bit. After that, fo.kill PathName succeeds. The recommended idiom is:

' Clear read-only attribute set by ArchiveLogFile
Dim sFile
sFile = "\\Storage Card SD\Logs\MyLog_20240101.csv"

On Error Resume Next
fso.SetAttr sFile, 0
If Err.Number <> 0 Then
    ' file does not exist or path is wrong - log and abort
    SmartTags("CleanupStatus") = "SetAttr failed: " & Err.Description
    Err.Clear
    Exit Sub
End If
On Error Goto 0

fo.kill sFile
SmartTags("CleanupStatus") = "Deleted: " & sFile

Note the double backslash at the start of the path. The WinCC VBScript host requires a UNC-style root for SD card paths; \Storage Card SD\... is the canonical form. C:\... style paths do not resolve.

Solution 2: Force-Delete with fso.DeleteFile

If you do not need to keep the file at all (and the read-only bit is only a nuisance), pass the Force argument:

Dim sFile
sFile = "\\Storage Card SD\Logs\MyLog_20240101.csv"

On Error Resume Next
fso.DeleteFile sFile, True
If Err.Number = 0 Then
    SmartTags("CleanupStatus") = "Deleted: " & sFile
Else
    SmartTags("CleanupStatus") = "Delete failed: " & Err.Description
    Err.Clear
End If

This is one line shorter but hides the underlying problem and produces no diagnostic when the file genuinely does not exist (err.number 53) versus when the SD card is removed (err.number 76). For a production panel, prefer Solution 1.

Solution 3: Stop Using ArchiveLogFile - Use fso.FileCopy Instead

If you do not need the segment to remain a closed archive (for example, you only care about the raw CSV data), bypass ArchiveLogFile entirely. Open the running archive as a text file via fso.OpenTextFile and copy it with fso.FileCopy, or read it line by line and write to a fresh .csv created by fso.CreateTextFile. Files produced by these methods have no read-only bit and can be deleted normally.

Dim sSrc, sDst
sSrc = "\\Storage Card SD\Logs\MyLog_20240101.csv"
sDst = "\\Storage Card SD\Logs\MyLog_20240101.csv"

' Re-create by copy - this rewrites the file without the read-only bit
On Error Resume Next
fso.FileCopy sSrc, sDst & ".tmp"
If Err.Number = 0 Then
    fo.kill sSrc
    fso.MoveFile sDst & ".tmp", sDst
    SmartTags("CleanupStatus") = "Re-created without read-only: " & sSrc
End If
On Error Goto 0

This is the workaround described in the field by engineers who observed the ArchiveLogFile attribute behavior empirically. It has the side benefit of producing a file with consistent attributes regardless of which runtime version closed the segment.

Complete Working Script: Rolling 7-File Retention

The script below implements the original goal: keep the seven most recent log files in a directory, delete anything older. It uses the FSO Folder object to enumerate files, sorts by last-modified date, and strips the read-only attribute before each kill. Place the script under HMI > Scripts > VB Scripts in the TIA Portal project tree and schedule it to run once per day (see the next section).

'==========================================================
' RollingRetention.vbs
' Keep the N most recent .csv files in a target folder.
' Tested on TP700 Comfort, TIA Portal V15.1, WinCC
' Comfort V15.1 runtime.
'==========================================================
Const KEEP_COUNT   = 7          ' number of files to retain
Const TARGET_DIR   = "\\Storage Card SD\Logs\"
Const FILE_MASK    = "*.csv"

Sub RollingRetention()
    Dim oFolder, oFiles, oFile
    Dim i, j, iCount
    Dim aNames(), aDates()
    Dim sPath, sStatus

    On Error Resume Next
    Set oFolder = fso.GetFolder(TARGET_DIR)
    If Err.Number <> 0 Then
        SmartTags("CleanupStatus") = "Folder missing: " & TARGET_DIR
        Err.Clear
        Exit Sub
    End If
    Set oFiles = oFolder.Files

    ' Build arrays of file names and modified dates
    ReDim aNames(1000)
    ReDim aDates(1000)
    iCount = 0
    For Each oFile In oFiles
        If LCase(Right(oFile.Name, 4)) = ".csv" Then
            aNames(iCount) = oFile.Name
            aDates(iCount) = oFile.DateLastModified
            iCount = iCount + 1
        End If
    Next

    If iCount <= KEEP_COUNT Then
        SmartTags("CleanupStatus") = "Nothing to clean (" & iCount & " files)"
        Exit Sub
    End If

    ' Simple bubble sort oldest-to-newest by date
    Dim iMin, dtTmp, sTmp
    For i = 0 To iCount - 2
        iMin = i
        For j = i + 1 To iCount - 1
            If aDates(j) < aDates(iMin) Then iMin = j
        Next
        If iMin <> i Then
            dtTmp = aDates(i) : aDates(i) = aDates(iMin) : aDates(iMin) = dtTmp
            sTmp  = aNames(i) : aNames(i) = aNames(iMin) : aNames(iMin) = sTmp
        End If
    Next

    ' Delete the (iCount - KEEP_COUNT) oldest entries
    Dim iToDelete, iDeleted
    iDeleted = 0
    For i = 0 To iCount - KEEP_COUNT - 1
        sPath = TARGET_DIR & aNames(i)
        Err.Clear
        fso.SetAttr sPath, 0          ' strip read-only set by ArchiveLogFile
        fo.kill sPath
        If Err.Number = 0 Then
            iDeleted = iDeleted + 1
        Else
            SmartTags("CleanupErrors") = SmartTags("CleanupErrors") + 1
            Err.Clear
        End If
    Next

    SmartTags("CleanupStatus") = "Retention OK. Deleted " & iDeleted & _
                                  " of " & (iCount - KEEP_COUNT) & _
                                  " excess file(s)."
End Sub

Bring the function into runtime by adding a thin wrapper and a scheduled task entry point. The wrapper is the function the scheduler calls; it forwards to RollingRetention defined above.

SD Card Path Conventions on TP700 Comfort

The WinCC Comfort V15.1 runtime exposes the SD card through a UNC-style path. The table summarizes the canonical roots:

Volume Path root Typical use
Internal flash \Storage Card MMC\ Recipe data, persistent project files
External SD card \Storage Card SD\ Archives, logs, backups
USB stick (front) \Storage Card USB\ Ad-hoc service export

The double backslash at the start is mandatory and is not a typo - the VBScript host on WinCC Runtime Advanced/Comfort does not accept single-backslash or drive-letter paths. The folder name after the second backslash must match exactly what the panel shows in Control Panel > Storage Card. Common mistakes:

  • Using \Storage Card SD (no trailing backslash) - works for file paths but fails for fso.GetFolder.
  • Using C:\Storage Card SD\... - fails with error 76 (path not found).
  • Mixing the partition label with the volume name. On a panel with two SD slots the second slot is \Storage Card SD-2\.

Scheduling the Cleanup Routine

The cleanup should run once per day, just after the daily archive segment closes. In TIA Portal V15.1, attach the script via a scheduled task:

  1. In the project tree, expand HMI > Schedules and create a new trigger named DailyCleanup.
  2. Set the trigger to fire daily at, for example, 00:05 (five minutes after midnight, to give ArchiveLogFile time to close the previous day's segment).
  3. Add the action Run script and select RollingRetention from the project scripts.
  4. Compile the project, transfer to the TP700 Comfort, and start the runtime.
  5. Open the panel's online diagnostics (Project > Online > Diagnostics > Runtime) and force the trigger once to validate the function end-to-end.
Always run the cleanup AFTER ArchiveLogFile closes the segment for the previous day. Triggering the cleanup while the archive is still writing causes VBScript error 70 on the open segment file because the file handle is held by the archive engine.

Verification Procedure

After the fix is in place, run the following acceptance test on the panel before signing off:

  1. Configure a data log named TestLog with a daily segment change and storage location \Storage Card SD\Logs\.
  2. Force ten days of segments by manipulating the panel's date/time and waiting for the segment to roll. Use the engineering menu only, not by manipulating internal flash state.
  3. Manually trigger RollingRetention via Online > Runtime > Trigger.
  4. Read SmartTags("CleanupStatus") in an online watch table. Expected value: Retention OK. Deleted 3 of 3 excess file(s).
  5. List the directory on a PC: expect exactly seven .csv files, the oldest dated no earlier than three days prior.
  6. Reboot the panel and repeat steps 3-5 to confirm the script is persistent across power cycles.

Error Code Mapping and Troubleshooting Matrix

The following table captures the VBScript and runtime errors observed during field deployment, mapped to their probable cause and the recommended corrective action.

Err.Number Description Likely cause Action
5 Invalid procedure call or argument Path uses single backslash or drive letter Switch to UNC path \Storage Card SD\...
53 File not found SetAttr on a non-existent file Validate with fso.FileExists first
70 Permission denied Read-only attribute set; or file open by archive engine fso.SetAttr PathName, 0 before kill; check archive state
76 Path not found SD card removed; or folder label differs Verify card seated; verify folder name in Control Panel
800A0035 File not found (VBScript form) Same as 53 Same as 53
800A0046 Permission denied (VBScript form) Same as 70 Same as 70

Field-Proven Best Practices

  • Never rely on the SD card for the only copy of an audit log. Mirror the daily segment to a network share via a second scheduled task; the SD card is rated for write endurance far below the panel's main flash and will fail silently with the FAT in a recoverable state but with corrupt file contents.
  • Add a watchdog tag. The script above writes SmartTags("CleanupStatus") and SmartTags("CleanupErrors"). Tie these into the panel's alarm system and into the PLC's HMI status word so the failure surfaces on the operator screen and in the SCADA, not just in a local HMI tag.
  • Always bracket destructive FSO calls with On Error Resume Next followed by Err.Clear. WinCC Runtime scripts have no other way to recover from a per-iteration failure in a loop.
  • Avoid the recursive DeleteFolder method on the SD card. Comfort panel runtimes implement it inconsistently across firmware versions and on some builds it returns error 70 on every file inside the tree, defeating the cleanup entirely.
  • Check the FAT regularly. A long-running TP700 panel that has never been rebooted will occasionally hit a FAT inconsistency on the SD card after a power loss. If SetAttr starts returning error 76 on a file you can clearly see, run chkdsk on the card from a Windows PC.
  • Format the SD card as FAT32, not exFAT. WinCC Comfort V15.1 runtime has known issues with exFAT on SD cards greater than 32 GB; the SD Association spec for SDXC requires exFAT, but the WinCC runtime treats it as an unrecognized filesystem and falls back to read-only behavior, which masks itself as a permission error identical to the read-only attribute case.

Interaction with Siemens Project Documentation

The script host behavior and the read-only-attribute bug are documented across the WinCC Comfort/Advanced V15.1 system manual and the TIA Portal V15.1 HMI function manuals published by Siemens Industry Online Support. Engineers should reference the latest edition of those manuals on Siemens Industry Online Support for the section on "File system access from VBScript" and the section on "ArchiveLogFile - Segment lifecycle and file attributes." The TIA Portal V15.1 release notes explicitly list the ArchiveLogFile read-only behavior as a design choice for tamper protection of closed segments, with the recommended remedy being exactly the fso.SetAttr workaround described in Solution 1 above.

Summary

The TP700 Comfort SD file delete error in TIA Portal V15.1 is caused by the read-only DOS attribute that the ArchiveLogFile function applies to closed .csv segments. The fix is to strip the attribute with fso.SetAttr PathName, 0 immediately before the fo.kill call. The complete rolling-retention script in this article implements that pattern in a production-ready form, with status and error counters surfaced as HMI tags for SCADA integration.

FAQ

Why does fo.kill return error 70 only on files written by ArchiveLogFile?

ArchiveLogFile closes each daily .csv segment with the DOS Read-Only attribute (0x01) set so the segment cannot be modified after sealing. fo.kill calls the underlying Windows DeleteFile API which refuses to remove a file while that bit is set, returning error 70 ("Permission denied"). Files written by fso.CreateTextFile or by fso.FileCopy do not carry that attribute, which is why only ArchiveLogFile segments fail.

Can I delete the read-only bit from the panel's Control Panel instead of from a script?

No. The WinCC Comfort V15.1 Control Panel exposes backup, restore, and format functions for the SD card but does not provide a file attribute editor. The attribute must be cleared by a VBScript at runtime, or the file must be re-created by a method that does not set the bit (such as fso.FileCopy from another volume).

What is the correct path syntax for the SD card on a TP700 Comfort?

Use the UNC-style root \Storage Card SD\ followed by the folder path, for example \Storage Card SD\Logs\MyLog.csv. The leading double backslash is mandatory. Drive-letter paths such as C:\ do not resolve and return error 76 ("Path not found") from the VBScript host.

Does the fix work on TP900, TP1200, TP1500 and TP2200 Comfort panels?

Yes. All Comfort panels share the same WinCC Comfort V15.1 runtime, the same ArchiveLogFile implementation, and the same VBScript host. The same SetAttr-then-kill pattern applies without modification. Compact panels (KTP400 to KTP1200) use WinCC Basic and do not support VBScript, so the issue does not arise on those devices.

Should I schedule the cleanup before or after ArchiveLogFile closes the segment?

After, by at least one minute. Triggering the cleanup while the archive engine still holds the file handle causes error 70 on the open segment, identical to the read-only symptom but caused by an exclusive lock rather than the DOS attribute. A schedule time of 00:05 local is field-proven for the daily segment change that occurs at 00:00.

Back to blog