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.
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 optionalForceargument set toTrue, it bypasses the read-only check and deletes the file. WithoutForce, 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:
- On the TP700 Comfort, insert the SD card and confirm the panel recognizes it under Control Panel > Storage Card.
- Trigger a manual archive backup from Control Panel > Backup/Restore so at least one closed
.csvsegment exists under\Storage Card SD\Logs\. - 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. - Uncheck Read-only on the PC, save the change, reinsert the SD card into the panel, and run the original
fo.killscript. If the file is now deleted, the read-only attribute is confirmed as the root cause. - 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.
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 forfso.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:
- In the project tree, expand HMI > Schedules and create a new trigger named
DailyCleanup. - Set the trigger to fire daily at, for example, 00:05 (five minutes after midnight, to give
ArchiveLogFiletime to close the previous day's segment). - Add the action Run script and select
RollingRetentionfrom the project scripts. - Compile the project, transfer to the TP700 Comfort, and start the runtime.
- Open the panel's online diagnostics (Project > Online > Diagnostics > Runtime) and force the trigger once to validate the function end-to-end.
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:
- Configure a data log named
TestLogwith a daily segment change and storage location\Storage Card SD\Logs\. - 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.
- Manually trigger
RollingRetentionvia Online > Runtime > Trigger. - Read
SmartTags("CleanupStatus")in an online watch table. Expected value:Retention OK. Deleted 3 of 3 excess file(s). - List the directory on a PC: expect exactly seven
.csvfiles, the oldest dated no earlier than three days prior. - 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")andSmartTags("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 Nextfollowed byErr.Clear. WinCC Runtime scripts have no other way to recover from a per-iteration failure in a loop. -
Avoid the recursive
DeleteFoldermethod 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
SetAttrstarts returning error 76 on a file you can clearly see, runchkdskon 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.