WinCC Recipe File Selection: Implementing Browse Folder Dialogs
Overview
Recipe management in Siemens WinCC typically relies on fixed default paths configured at design time. When integrators need to allow operators to select the destination folder for recipe export or the source folder for recipe import (for example, when copying recipes to a USB flash drive on the operator terminal), WinCC's standard recipe functions are not sufficient. The runtime must invoke a native folder-browser or file-selection dialog that returns a user-chosen path to the script host.
This article documents four working approaches to expose a folder or file picker in WinCC V7 and WinCC flexible 2007/2008 SP3 runtimes (Build V1.2.0.0_1.55.0.1) — including the corrected C-Script using comdlg32.dll, VBScript with the MSComDlg.CommonDialog ActiveX control, VBScript with Shell.Application.BrowseForFolder, and the WinCC HMIRuntime.FileSystem object for direct USB file I/O. Each solution ships with copy-paste code, error-handling macros, and a verification sequence.
comdlg32.dll will not compile when pasted into a WinCC VBScript editor. VBScript does not support #pragma, char, struct, or pointer syntax. The code must be placed in a C-Script action and wrapped in a function, or rewritten in pure VBScript using the Microsoft Common Dialog Control or the Shell object.Why the Original C Code Fails in VBScript
The published snippet uses constructs that are not part of the VBScript language:
-
#pragma code("comdlg32.dll")— a WinCC C-Script pragma directive, unknown to the VBScript compiler -
#include "commdlg.h"— a C preprocessor directive -
char szFilter[],char* psz,char szFile[_MAX_PATH+1]— typed C buffers -
strcpy()— a C runtime function -
FindWindow(NULL, "WinCC-Runtime - ")— a Win32 API call returning a handle that VBScript cannot use -
OPENFILENAME ofn— a C struct, not a VBS class
When the VBScript parser encounters #pragma on line 1, it reports "Unknown command" and aborts the compile. The fix is to use the WinCC C-Editor (not the VBScript-Editor) for the snippet, or rewrite the entire dialog in VBScript using the Microsoft Common Dialog ActiveX or the Shell object.
To determine which editor is currently active, look at the title bar of the script window: it reads "Edit VBS-Action" or "Edit C-Action". Switching is done via the dropdown next to the save button in WinCC V7.0/V7.1, or via the action's context menu in WinCC V7.3 and later.
WinCC Scripting Environment Requirements
WinCC V7 separates scripts into two editors with different language bindings:
| Editor | Language | Host | Typical Use |
|---|---|---|---|
| VBScript Editor | VBScript (vbs) | WScript / WinCC VBS host | Tag I/O, file I/O, math, dispatch to COM |
| C-Editor | ANSI C with WinCC API | WinCC C compiler (internal BCC) | Win32 API calls, #pragma includes, performance-critical loops |
Each action in a WinCC picture is bound to one language at creation time. The action's "Programming language" property in the WinCC Explorer attribute panel reflects the binding. Switching language after the action contains code strips out incompatible directives — for example, switching from C to VBS drops every #pragma line without warning.
commdlg.h inclusion.Solution 1: Corrected C-Script with comdlg32.dll
Create a new action in the WinCC C-Editor, paste the source, and wrap the body in a function so the C compiler emits a callable symbol. The action is bound to a button's Mouse-Click event:
// WinCC C-Action: Open file dialog for recipe import
// Bind to button "Click" event
#include "apdefap.h"
#pragma code("comdlg32.dll")
#include "commdlg.h"
#pragma code()
BOOL OnOpenRecipeFile(LPCSTR lpszDefaultName)
{
OPENFILENAME ofn;
char szFilter[] = "CSV Files (*.csv)|*.csv|TXT Files (*.txt)|*.txt|All Files (*.*)|*.*|";
char* psz;
char szFile[_MAX_PATH+1];
char szFileTitle[_MAX_PATH+1];
char szInitialDir[_MAX_PATH+1];
HWND hwndOwner;
BOOL bResult;
for (psz = szFilter; *psz; psz++) {
if (*psz == '|') {
*psz = 0;
}
}
strcpy(szInitialDir, "C:\\Recipes");
strcpy(szFile, lpszDefaultName);
strcpy(szFileTitle, lpszDefaultName);
hwndOwner = FindWindow(NULL, "WinCC-Runtime - ");
memset(&ofn, 0, sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hwndOwner;
ofn.lpstrFilter = szFilter;
ofn.lpstrFile = szFile;
ofn.nMaxFile = _MAX_PATH + 1;
ofn.lpstrFileTitle = szFileTitle;
ofn.nMaxFileTitle = _MAX_PATH + 1;
ofn.lpstrInitialDir = szInitialDir;
ofn.Flags = OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "csv";
bResult = GetOpenFileName(&ofn);
if (bResult) {
printf("Selected file: %s\r\n", ofn.lpstrFile);
SetTagChar("RecipeSelectedPath", ofn.lpstrFile);
return TRUE;
} else {
DWORD err = CommDlgExtendedError();
printf("GetOpenFileName failed, code 0x%04X\r\n", err);
return FALSE;
}
}
Four corrections versus the unmodified snippet circulated in engineer forums:
- The body is wrapped in
OnOpenRecipeFile(); WinCC C actions must define a function whose symbol matches the action name, otherwise the C compiler discards the body as unreferenced. -
strcpy(szFile, lpszDefaultName)initializes the file-name buffer beforeGetOpenFileNamewrites into it. The original code passed an uninitialized buffer;OPENFILENAMErequires the first byte oflpstrFileto be a valid NUL-terminated string whenOFN_FILEMUSTEXISTis not set. -
memset(&ofn, 0, sizeof(OPENFILENAME))zeroes reserved fields.OPENFILENAMEhas grown between Windows releases (Vista, Win7, Win10 added new fields); the OS reads these bytes and returns0x0002(CDERR_DIALOG) fromCommDlgExtendedErrorif they contain garbage. -
OFN_HIDEREADONLYis added to hide the legacy "Open as read-only" checkbox that confuses operators on Vista+ dialogs.
For Save As (recipe export), replace GetOpenFileName with GetSaveFileName and add OFN_OVERWRITEPROMPT (already present). To start the dialog on a USB drive, set szInitialDir to "E:\\Recipes\\" or read the drive letter from a WinCC tag set by an operator scan action.
Common CommDlgExtendedError Codes
| Hex | Constant | Meaning | Resolution |
|---|---|---|---|
| 0x0001 | CDERR_DIALOGFAIL | Dialog box could not be created | Check hwndOwner validity; reduce stack usage in caller |
| 0x0002 | CDERR_STRUCTSIZE |
lStructSize wrong or struct not zeroed |
Set sizeof(OPENFILENAME) and memset the struct |
| 0x0003 | CDERR_INITIALIZATION | COM init failed | Reboot runtime; check DCOM service status |
| 0x0004 | CDERR_NOTEMPLATE | Template resource missing | Remove OFT_TEMPLATENAME flag |
| 0x0006 | CDERR_LOADRESFAILURE | Template resource load failed | Verify resource path |
| 0x000A | CDERR_MEMALLOCFAILURE | Heap allocation failed | Close other dialogs; check available memory |
| 0x000B | CDERR_LOCKRESFAILURE | Cannot lock resource | Reboot; check file system |
| 0x1001 | FNERR_BUFFERLENGTH | Buffer too small for filename | Set nMaxFile = MAX_PATH; pre-initialize szFile
|
| 0x1006 | FNERR_INVALIDFILENAME | File name pattern invalid | Strip *, ?, | from pattern |
Solution 2: VBScript with MSComDlg.CommonDialog ActiveX Control
If the project must remain in VBScript (for example, to call other VBS functions from the same project), drop the Microsoft Common Dialog Control on the WinCC picture and use it from VBScript. The control's ProgID is MSComDlg.CommonDialog and is shipped with comdlg32.ocx (part of the Visual Basic 6 runtime).
Add the control to the picture:
- Open the Graphics Designer and place an ActiveX Control on the picture from the Smart Objects palette.
- In the wizard, pick Microsoft Common Dialog Control, Version 6.0. If it does not appear, install the VB6 runtime (shipped with many Siemens engineering tools) and re-register:
regsvr32 comdlg32.ocxfrom an elevated command prompt. - Rename the control to
ComDlg1in the object properties.
VBScript action bound to a button Click event:
' WinCC VBScript action
Sub OnClick(ByVal Item)
Dim sFilter, sPath, iCancelErr
iCancelErr = 32755 ' CDERR_CANCEL raised by CancelError=True
ComDlg1.CancelError = True
sFilter = "CSV Files (*.csv)|*.csv|TXT Files (*.txt)|*.txt|All Files (*.*)|*.*|"
sFilter = Replace(sFilter, "|", vbNullChar)
sFilter = sFilter & vbNullChar & vbNullChar
On Error Resume Next
ComDlg1.Flags = &H4& ' OFN_PATHMUSTEXIST
ComDlg1.Filter = sFilter
ComDlg1.InitDir = "C:\Recipes"
ComDlg1.FileName = "recipe_001.csv"
ComDlg1.DialogTitle = "Select recipe file"
ComDlg1.ShowOpen
If Err.Number = 0 Then
sPath = ComDlg1.FileName
HMIRuntime.Tags("RecipeSelectedPath").Write sPath
HMIRuntime.Trace "Selected file: " & sPath & vbNewLine
ElseIf Err.Number = iCancelErr Then
HMIRuntime.Trace "User cancelled the dialog" & vbNewLine
Else
HMIRuntime.Trace "ComDlg error: " & Err.Number & " " & Err.Description & vbNewLine
End If
On Error Goto 0
End Sub
The Replace call converts Win32 double-NUL filter pairs (e.g. "CSV|*.csv|") into single-NUL delimiters with a trailing double NUL, which the COM property expects. The flag value &H4& is OFN_PATHMUSTEXIST (see the OPENFILENAME flag table in the Windows SDK headers commdlg.h). The error code 32755 (0x800B) is the documented CDERR_CANCEL "user pressed Cancel" trap raised when CancelError = True.
For ShowSave (recipe export), swap the last ShowOpen line for ComDlg1.ShowSave and add ComDlg1.Flags = &H4& Or &H2& (path must exist + overwrite prompt).
comdlg32.ocx. Test on the actual runtime image before deployment, and bundle comdlg32.ocx in the project deployment directory so the installer can re-register it on first run.Solution 3: VBScript with Shell.Application for Folder Browsing
For pure folder selection (browse a directory tree, no file), the Windows Shell object provides a native folder-picker via Shell.BrowseForFolder. This is a single-call API that requires no ActiveX registration and works on every Windows version from XP onward, including Windows 10 IoT LTSC images shipped with WinCC V7.4/V7.5 runtime PCs.
' WinCC VBScript action - folder picker for recipe destination
Sub OnClick(ByVal Item)
Dim oShell, oFolder, sPath
Const BIF_RETURNONLYFSDIRS = &H1
Const BIF_EDITBOX = &H10
Const BIF_NEWDIALOGSTYLE = &H40
Const BIF_USENEWUI = &H50 ' BIF_EDITBOX Or BIF_NEWDIALOGSTYLE
Set oShell = CreateObject("Shell.Application")
Set oFolder = oShell.BrowseForFolder(0, _
"Select destination folder for recipe export", _
BIF_RETURNONLYFSDIRS Or BIF_USENEWUI, _
"C:\Program Files\Siemens\Automation")
If Not oFolder Is Nothing Then
sPath = oFolder.Self.Path
HMIRuntime.Tags("RecipeExportFolder").Write sPath
HMIRuntime.Trace "Folder selected: " & sPath & vbNewLine
Else
HMIRuntime.Trace "Folder selection cancelled" & vbNewLine
End If
Set oFolder = Nothing
Set oShell = Nothing
End Sub
Flag decoding (from the Windows SDK header shlobj.h):
| Constant | Value | Effect |
|---|---|---|
| BIF_RETURNONLYFSDIRS | 0x0001 | Return only file system directories; hide Control Panel, Recycle Bin, My Computer |
| BIF_DONTGOBELOWDOMAIN | 0x0002 | Disable network traversal beyond the local domain |
| BIF_STATUSTEXT | 0x0004 | Show status text area at the bottom of the dialog |
| BIF_BROWSEFORCOMPUTER | 0x1000 | Return computer names only (network neighborhood style) |
| BIF_BROWSEFORPRINTER | 0x2000 | Return printer names only |
| BIF_EDITBOX | 0x0010 | Add an editable path text box at the top of the dialog |
| BIF_NEWDIALOGSTYLE | 0x0040 | Use the resizable Vista+ dialog with breadcrumb bar and address bar |
| BIF_USENEWUI | 0x0050 | Convenience alias: EDITBOX Or NEWDIALOGSTYLE
|
For USB-aware folder selection, scan the file system for removable drives before invoking the dialog and pass the detected root as the start folder:
Function GetRemovableDriveRoot()
Dim oFSO, oDrive, sResult
Set oFSO = CreateObject("Scripting.FileSystemObject")
sResult = ""
For Each oDrive In oFSO.Drives
If oDrive.DriveType = 1 Then ' 1 = Removable
sResult = oDrive.Path & "\"
Exit For
End If
Next
GetRemovableDriveRoot = sResult
Set oFSO = Nothing
End Function
Sub OnClick(ByVal Item)
Dim oShell, oFolder, sPath, sStartDir
sStartDir = GetRemovableDriveRoot()
If Len(sStartDir) = 0 Then sStartDir = "C:\Recipes"
Set oShell = CreateObject("Shell.Application")
Set oFolder = oShell.BrowseForFolder(0, _
"Select destination folder for recipe export", _
&H1 Or &H50, _
sStartDir)
If Not oFolder Is Nothing Then
sPath = oFolder.Self.Path
HMIRuntime.Tags("RecipeExportFolder").Write sPath
End If
Set oFolder = Nothing
Set oShell = Nothing
End Sub
The DriveType values per the Scripting.FileSystemObject documentation: 0 = Unknown, 1 = Removable, 2 = Fixed, 3 = Network, 4 = CD-ROM, 5 = RAM Disk.
Solution 4: Using WinCC HMIRuntime.FileSystem for Direct USB Access
WinCC V7 exposes a high-level file system object that abstracts the Microsoft Scripting Runtime FileSystemObject. From runtime scripts the helper is HMIRuntime.FileSystem and it is the recommended way to copy recipe CSV files to and from a USB stick without invoking an external dialog:
Function ExportRecipeToUSB(sSourceFile, sUSBTargetFolder)
Dim oFS, sDestPath
Set oFS = CreateObject("Scripting.FileSystemObject")
If Not oFS.FolderExists(sUSBTargetFolder) Then
oFS.CreateFolder sUSBTargetFolder
End If
sDestPath = oFS.BuildPath(sUSBTargetFolder, oFS.GetFileName(sSourceFile))
oFS.CopyFile sSourceFile, sDestPath, True
HMIRuntime.Trace "Recipe exported to " & sDestPath & vbNewLine
Set oFS = Nothing
ExportRecipeToUSB = sDestPath
End Function
Function ImportRecipeFromUSB(sUSBFilePath, sDestFolder)
Dim oFS, sDestPath
Set oFS = CreateObject("Scripting.FileSystemObject")
If Not oFS.FileExists(sUSBFilePath) Then
Err.Raise vbObjectError + 1001, , "Source file not found: " & sUSBFilePath
Exit Function
End If
sDestPath = oFS.BuildPath(sDestFolder, oFS.GetFileName(sUSBFilePath))
oFS.CopyFile sUSBFilePath, sDestPath, True
Set oFS = Nothing
ImportRecipeFromUSB = sDestPath
End Function
To detect the USB letter dynamically, enumerate HMIRuntime.FileSystem.Drives (WinCC V7.4+) or use the classic FileSystemObject.Drives enumeration as in GetRemovableDriveRoot above. The detection loop must run on a 1-second scheduler with a short delay (WinCC USB enumeration on Windows 7/10 can take 1-3 seconds after the user inserts the stick). Verify drive readiness with oFS.Drive.IsReady before opening any file — a not-yet-ready drive returns a generic error 0x800A0046 (permission denied) instead of a clean "device not ready" code.
Recipe Management Workflow Implementation
A typical recipe import/export flow on a WinCC Runtime PC is:
- Operator inserts USB stick; a WinCC scheduler action polls
FSO.Drivesevery 1 s and writes the first removable drive letter to the internal tagUSB_DriveLetter. - Operator presses the Export Recipe button. The C-Action from Solution 1 calls
GetSaveFileNamewithszInitialDirinitialized toUSB_DriveLetter+":\\Recipes\\". - Operator chooses a target file name. The action writes the path to tag
RecipeSelectedPathand callsExportRecipeToUSB()from Solution 4. - For import, the operator presses Import Recipe. The VBScript action from Solution 2 or 3 retrieves a path and calls
ImportRecipeFromUSB(). - WinCC reads the imported CSV into internal recipe tags, using either the built-in recipe view (WinCC flexible / Comfort Panels / TIA Portal) or a custom
OpenTextFileparse in WinCC V7 PC runtime.
Sample CSV parse in VBScript for a 3-parameter recipe (parameter, value, unit):
Function ParseRecipeCSV(sFilePath)
Dim oFSO, oFile, sLine, aFields, dResult
Set dResult = CreateObject("Scripting.Dictionary")
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.OpenTextFile(sFilePath, 1, False, -1)
' Arguments: 1=ForReading, False=create=False, -1=Unicode (auto-detect BOM)
Do While Not oFile.AtEndOfStream
sLine = Trim(oFile.ReadLine)
If Left(sLine, 1) <> "'" And Len(sLine) > 0 Then
aFields = Split(sLine, ",")
If UBound(aFields) >= 1 Then
If Not dResult.Exists(aFields(0)) Then
dResult.Add aFields(0), aFields(1)
End If
End If
End If
Loop
oFile.Close
Set oFile = Nothing
Set oFSO = Nothing
Set ParseRecipeCSV = dResult
End Function
Sub ApplyRecipeToTags(dRecipe)
If dRecipe.Exists("Temperature") Then _
HMIRuntime.Tags("Recipe.Temperature").Write CDbl(dRecipe("Temperature"))
If dRecipe.Exists("Pressure") Then _
HMIRuntime.Tags("Recipe.Pressure").Write CDbl(dRecipe("Pressure"))
If dRecipe.Exists("CycleTime") Then _
HMIRuntime.Tags("Recipe.CycleTime").Write CDbl(dRecipe("CycleTime"))
End Sub
For a project that uses the WinCC Comfort Panel Recipe view (TIA Portal, firmware V14+), the recipe CSV is named RecipeData.csv with a fixed column header order. Do not overwrite this file with custom export logic — read it instead, or write to a separate user-recipe file. See the TIA Portal Help → Visualizing processes → Recipes → Structure of the recipe data file for the exact column ordering.
Error Handling and Diagnostics
Common failure modes when implementing these dialogs in WinCC:
| Symptom | Root Cause | Fix |
|---|---|---|
| "Unknown command" at first line of C code | Pasted in VBScript editor | Move to C-Editor; verify editor toolbar shows "C" |
| Dialog opens behind WinCC window | Wrong hwndOwner from FindWindow | Use NULL or GetForegroundWindow(); ensure WinCC Runtime window title matches FindWindow argument |
| CommDlgExtendedError 0x0002 (FNERR_STRUCTSIZE) | OPENFILENAME struct not zeroed | Add memset(&ofn, 0, sizeof(OPENFILENAME)) before populating fields |
| CommDlgExtendedError 0x1001 (FNERR_BUFFERLENGTH) | szFile buffer too small or uninitialized | Set nMaxFile = MAX_PATH, memzero buffer, pre-fill lpstrFile
|
| BrowseForFolder returns Nothing on Cancel | Correct Windows behavior | Test Is Nothing; do not raise an error |
| USB drive not visible | WinCC runtime running as service or UAC-restricted | Run WinCC Runtime as interactive user; disable UAC remote restrictions on the operator terminal |
| 0x80070005 (E_ACCESSDENIED) on file copy | User lacks write permission on USB | Check oFSO.Drive.IsReady and oFSO.Drive.AvailableSpace before copy |
| 0x800A0046 on file open | USB stick not enumerated yet | Wait 1-3 s after insertion; recheck IsReady in a loop |
| ActiveX MSComDlg control not listed in wizard | VB6 runtime not installed | Install VB6 runtime; regsvr32 comdlg32.ocx from elevated cmd |
| Recipe values applied as 0 | String contains non-numeric or locale-specific decimal | Use CDbl(Replace(sVal, ",", ".")) for non-US locales; handle decimal separator via CCur
|
| BrowseForFolder returns \My Computer\ path | User selected a special folder, not a file system path | Always use BIF_RETURNONLYFSDIRS and validate path starts with a drive letter |
Enable WinCC diagnostic output during commissioning by adding a C printf() or VBS HMIRuntime.Trace calls; results appear in the WinCC Diagnosis Viewer (ApDiag.exe) or in WinCC_<computername>.LOG in the project log folder. The default trace level is "Error" — change to "All" via the computer's WinCC Explorer → Computer → Properties → Startup for first-time debug.
Security and Path Validation
Allowing the operator to pick any path is a security vector. Apply these constraints in production deployments:
- Whitelist allowed root directories:
"E:\\Recipes\\","C:\\ProgramData\\Siemens\\Automation\\Recipes\\". Reject paths that do not start with the whitelist usingInStr(1, sPath, "E:\Recipes", vbTextCompare) = 1(returns 1 only if path begins with the prefix). - Sanitize file names to reject
..,\,:,*,?,",<,>,|in the recipe name field before concatenation. - Cap file size on import:
oFSO.GetFile(sFile).Size > 1048576(1 MB) → reject. Recipe files are typically under 100 KB; 1 MB is a generous ceiling that still protects against zip-bomb-style attacks. - Run WinCC Runtime under a dedicated operator user (not Administrator) so that file writes to USB are restricted by NTFS ACL to specific device instances. On Windows 10 IoT LTSC, USB device ACLs are configured in
Device Manager → Removable Disk → Properties → Security. - Use signed recipes: include a CRC-32 or HMAC-SHA1 of the file in the first CSV row, verify before applying tag values. The HMAC key should be stored in the WinCC project as a hashed constant, not in the CSV.
- Disable
Shell.Applicationfor untrusted users: set the WinCC Runtime user's group policy User Configuration → Administrative Templates → Windows Components → File Explorer → Prevent access to drives from My Computer to whitelist the USB letter only.
Verification and Testing
Validate the implementation with this sequence on a test PC matching the production image:
- Insert a USB stick; confirm the tag
USB_DriveLetterupdates within 5 seconds via the online tag view in WinCC Explorer. - Click Export Recipe; confirm
GetSaveFileNameopens at the USB root directory, not at the WinCC install path. - Save
test_recipe.csvwith 3 rows of comma-separated values; pull the stick, open the file in Excel or Notepad, confirm 3 data lines plus 1 header line. - Re-insert the stick; click Import Recipe; select
test_recipe.csv; confirm tagsRecipe.Temperature,Recipe.Pressure,Recipe.CycleTimereflect CSV values via online tag view in WinCC Explorer. - Click Cancel in the dialog; confirm the script logs "cancelled" via
HMIRuntime.Tracewithout raising a VBS runtime error or showing an error popup. - Test with multiple removable drives attached (USB hub); confirm the script picks the first detected one and continues if the user selects a different drive letter in the dialog.
- Test the file type filter: confirm only
*.csvfiles are listed when the filter is set; switch the filter to*.txtand confirm*.csvfiles disappear. - Test with a non-FAT32 USB stick (exFAT or NTFS) to confirm the file copy handles long paths (> 256 chars) and Unicode file names.
- Test with a write-protected USB stick; confirm the script raises a clean error ("USB is write-protected") rather than crashing.
- Test with the USB stick removed mid-operation; confirm the copy fails gracefully and the operator sees a message, not a frozen screen.
On Siemens Comfort Panels (TIA Portal, firmware V14+), the same logic applies but the MSComDlg ActiveX is not available — use the C-Script editor (Panel C-Script) with #pragma code("comdlg32.dll") exactly as in Solution 1. Panel C-Script has the same Windows API surface as WinCC V7 PC C-Script for the dialog APIs. For SIMATIC WinCC Unified (V16/V17/V18) the recommended pattern is to instantiate System.Windows.Forms.FolderBrowserDialog from a .NET script in a custom control; the unmanaged Win32 dialogs from Solutions 1-3 are not required and not supported on Unified runtime.
FAQ
Why does the comdlg32.dll C code fail with "Unknown command" in WinCC?
The script was pasted into the WinCC VBScript editor. WinCC ships two separate editors: VBScript and C. The C-Editor supports #pragma code("comdlg32.dll") and the OPENFILENAME struct; the VBScript editor does not. Switch the action's programming language to C via the editor toolbar or right-click → Convert to C in WinCC V7.3 and later.
How do I open a folder-picker dialog in VBScript without MSComDlg?
Use Shell.Application via CreateObject("Shell.Application") and call BrowseForFolder with the BIF_RETURNONLYFSDIRS and BIF_USENEWUI flags (combined value 0x51). The selected folder's path is returned through oFolder.Self.Path. No ActiveX registration is required and the dialog works on every Windows version from XP onward.
How do I detect the USB drive letter from WinCC runtime?
Enumerate drives with the Windows Scripting Runtime FileSystemObject: For Each oDrive In CreateObject("Scripting.FileSystemObject").Drives: If oDrive.DriveType = 1 Then sLetter = oDrive.Path. DriveType 1 = Removable. Run the detection on a 1 s scheduler because USB enumeration on Windows can take 1-3 s after insertion; always check oDrive.IsReady before opening files.
Which file dialog is the safest for production?
The VBScript Shell.Application.BrowseForFolder with BIF_RETURNONLYFSDIRS plus a path-prefix whitelist check (e.g. InStr(1, sPath, "E:\Recipes", vbTextCompare) = 1) is the safest. It avoids ActiveX dependencies, returns only file system paths, and gives the integrator a single point of validation before any file I/O is performed.
Can I use FolderBrowserDialog (.NET) in WinCC V7 VBScript?
No. System.Windows.Forms.FolderBrowserDialog is a .NET class and cannot be instantiated from VBScript via CreateObject. For WinCC Unified (V16+) you can call it from a .NET-scripted custom control on a Unified PC runtime, but for WinCC V7 the supported unmanaged options are Shell.BrowseForFolder and the C-Script comdlg32 dialogs documented in Solutions 1-3.