1. Problem Statement and Symptoms
When a WinCC runtime script attempts to launch an external executable that opens a file located on a remote computer, the call can fail with one of the following system errors, even when the local path version of the same call succeeds:
- 0x000006BA / HRESULT_FROM_WIN32(ERROR_RPC_S_SERVER_UNAVAILABLE) — The RPC server is unavailable.
- 1326 (0x52E) — ERROR_LOGON_FAILURE — "Logon failure: unknown user name or bad password." This is the error most frequently reported on Siemens support threads for this scenario.
- 1327 (0x52F) — ERROR_ACCOUNT_RESTRICTION — Account restrictions prevent the logon.
- 1330 (0x532) — ERROR_PASSWORD_EXPIRED — The password of the referenced account has expired.
- 5 (0x5) — ERROR_ACCESS_DENIED — Generic access denied when share permissions block the read but a graceful logon does not occur.
- 53 (0x35) — ERROR_BAD_NETPATH — The network path was not found (DNS/NetBIOS resolution failure, SMB not enabled, or LmCompatibilityLevel blocking NTLMv1).
A typical failing C call inside a WinCC Global Script action looks like this:
ProgramExecute("NotePad.exe \\\\SERVER\\D$\\ALARMS\\Alarms.txt");
While the same call against a local path:
ProgramExecute("NotePad.exe D:\\ALARMS\\Alarms.txt");
works without error. The behavioural asymmetry between the two cases is the diagnostic signature of an authentication context mismatch, not a WinCC scripting defect.
2. Root Cause Analysis
WinCC runtime executes under a specific Windows identity. The identity that matters is the one bound to the process hosting the script, not the identity of the operator currently logged in at the WinCC console. In a default WinCC installation this is the account under which the CCAlg.exe, PDLrt.exe and scriptrt.exe host processes are running. The mismatch is therefore between:
- The account the WinCC service host is running as (often SYSTEM, LOCAL SERVICE, or a dedicated operator account).
- The account that is authorised to read the remote file and traverse the share on the file server.
Three different Windows security layers must be satisfied for a UNC path to resolve and an executable to be spawned against the remote file:
| Layer | What it controls | Where it lives |
|---|---|---|
| SMB session | Connection to the share | Server share ACL (Computer Management > Shared Folders > Shares) |
| NTFS ACL | Read/execute on the file or directory | File system (Properties > Security) |
| Logon session | Validated identity under which the call runs | Local Security Authority (LSASS) on the target |
The classic failure path is: the WinCC process is running as SYSTEM, the share \\SERVER\D$ (or \\SERVER\ALARMS) is configured with the default ACL that grants access only to Administrators and the share's owner. SYSTEM on CLIENT is not the same principal as SYSTEM on SERVER across the network, so a NULL-session or anonymous binding is attempted. The target returns ERROR_LOGON_FAILURE because the inbound account cannot be validated.
3. UNC Path Conventions in WinCC
There are two distinct UNC forms that a WinCC script can address, and they require different levels of access:
| UNC form | Example | Access requirements |
|---|---|---|
| Hidden administrative share | \\SERVER\D$ |
Caller must be a member of the target's local Administrators group, or the Access this computer from the network user right on the target. |
| Standard share |
\\SERVER\ALARMS mapped from D:\ALARMS
|
Caller must be granted the share's ACL (Read, Change, or Full Control depending on intent). |
Hidden administrative shares (C$, D$, …) are disabled by default on Windows Server installations that follow the Windows Server role-hardening baseline. Microsoft documents the disablement and the registry key AutoShareServer / AutoShareWks in the File Server Resource Manager Connect to a Remote Computer reference, and they are surfaced again in the Server Manager and File Server Resource Manager (FSRM) console. For any production WinCC deployment the correct pattern is therefore a named share, not the administrative default shares.
The recommended share layout is:
- Create a dedicated share, for example
ALARMS, pointing toD:\ALARMSon SERVER. - Set the share ACL to grant Read (or Change if the script will write) to the specific service account or operator group.
- Remove the Everyone entry unless the system has an explicit reason to keep it.
- Configure the NTFS ACL on
D:\ALARMSto match. Share permissions are the upper bound; NTFS permissions are the effective lower bound; both are evaluated.
Once the share is created, the WinCC script becomes:
ProgramExecute("NotePad.exe \\\\SERVER\\ALARMS\\Alarms.txt");
This is the same standard server share pattern referenced in the field-tested guidance, where the share name follows the WinCC project convention \\<Server>\WinCC_<ProjectName> when sharing the entire project directory.
4. Aligning the WinCC Service Identity
The next constraint is to make sure the WinCC runtime is running as an identity that is recognised by the file server. There are three supported configurations.
4.1 Local System with Local Accounts on Both Endpoints
Use this only for development, demos, or single-segment test cells. Configure identical local user accounts (same username and same password) on both CLIENT and SERVER. Because the password hash matches, SYSTEM-level outbound calls on CLIENT will succeed on SERVER via NTLM pass-through. This configuration is brittle: it is not domain-aware, breaks when the password is rotated, and is the source of most "it worked yesterday" tickets.
4.2 Domain User Account for the WinCC Service
The recommended production configuration. Create a dedicated domain user, for example svc-wincc, with the following properties:
- User cannot change password.
- Password never expires (rotate manually on a documented schedule).
- Member of WinCC Users (local group on the WinCC host) and SCADA-File-Read (domain group with NTFS Read on
D:\ALARMS). - Logon permitted only on the WinCC runtime hosts via the Logon To… account option.
Configure the WinCC runtime services to log on as this account. In the Windows Services console (services.msc), change the logon of:
- SIMATIC WinCC Explorer (WinCC Explorer runtime instance)
- CCAlg — Alarm Logging service
- CCArchive — Tag Logging service
- ScriptRT — Global Script runtime
Set the service to log on with the svc-wincc domain user. Restart the services so the new logon context is loaded.
4.3 Constrained Delegation for Multi-Hop Architectures
When the WinCC runtime must reach a file server on a different trust boundary, or when additional hops are required (for example, WinCC → relay → file server), configure Kerberos constrained delegation on the WinCC service account. The relevant Microsoft article is the Connect to a Remote Computer documentation, which sets the security baseline for File Server Resource Manager and the SMB stack.
Constrained delegation is configured in Active Directory Users and Computers on the svc-wincc account, Delegation tab, and the SPNs you add are cifs/<fileserver> and cifs/<fileserver.fqdn>. This is also the path to take if WinCC will be calling net use, WNetAddConnection2 or ShellExecute against the same remote target.
5. Code Patterns That Work
5.1 C Global Script with mapped drive
#include "apdefap.h"
void OnClick(char* lpszPictureName, char* lpszObjectName, char* lpszPropertyName, UINT nHwnd, char* lpszPictureName_2)
{
// Map the share under the process identity
NETRESOURCE nr;
memset(&nr, 0, sizeof(nr));
nr.dwType = RESOURCETYPE_DISK;
nr.lpLocalName = "Z:";
nr.lpRemoteName = "\\\\SERVER\\ALARMS";
nr.lpProvider = NULL;
DWORD dwResult = WNetAddConnection2(
&nr,
NULL, // password – use default credentials
NULL, // user – use default credentials (process identity)
CONNECT_INTERACTIVE | CONNECT_COMMANDLINE
);
if (dwResult == NO_ERROR || dwResult == ERROR_ALREADY_ASSIGNED) {
ProgramExecute("NotePad.exe Z:\\Alarms.txt");
if (dwResult == NO_ERROR) WNetCancelConnection2("Z:", 0, TRUE);
} else {
printf("Map failed: %lu\r\n", dwResult);
}
}
When using WNetAddConnection2 with NULL user and password, the call binds the share to the current process token. If the WinCC service is running as svc-wincc, the share is bound under that identity. If it is running as SYSTEM, the binding will fail with ERROR_LOGON_FAILURE unless the SERVER is in a domain and the file server is configured to trust SYSTEM (rare).
5.2 VBScript Using HMIRuntime / Shell.Application
Sub OnClick(ByVal Item)
Dim objShell, objExec
Set objShell = CreateObject("Shell.Application")
Dim sRemotePath
sRemotePath = "\\\\SERVER\\ALARMS\\Alarms.txt"
On Error Resume Next
objShell.ShellExecute "notepad.exe", sRemotePath, , , 1
If Err.Number <> 0 Then
HMIRuntime.Trace "ShellExecute error: 0x" & Hex(Err.Number) & " - " & Err.Description & vbCrLf
End If
On Error Goto 0
End Sub
The Shell.Application COM object resolves UNC paths and prompts for credentials interactively only if the calling process is running under a user session that has UI access. In a Windows service context the prompt is suppressed and the call fails with the same ERROR_LOGON_FAILURE. The same fix — running the service under a known domain identity — applies.
5.3 PowerShell Launcher from WinCC
Sub OnClick(ByVal Item)
Dim objShell, sCmd
sCmd = "powershell.exe -NoProfile -Command ""Start-Process 'notepad.exe' -ArgumentList '\\\\SERVER\\ALARMS\\Alarms.txt'"""
Set objShell = CreateObject("Shell.Application")
objShell.ShellExecute "powershell.exe", "-NoProfile -Command ""Start-Process 'notepad.exe' -ArgumentList '\\\\SERVER\\ALARMS\\Alarms.txt'""", , , 0
End Sub
This is the most flexible path when the WinCC host runs on a desktop OS and the operator is an interactive user. The launch runs under the operator's token, not the service's, and inherits whatever share bindings the operator's logon session has negotiated.
6. Common Error Codes and Their Meaning
| Win32 code | HRESULT | Meaning in this context | Likely fix |
|---|---|---|---|
| 5 | 0x80070005 | Access denied at NTFS layer | Grant Read on the file/directory to the calling identity |
| 53 | 0x80070035 | Network path not found | Check DNS, NetBIOS, firewall (TCP 445), SMB1 disabled |
| 1219 | 0x800704C3 | Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed | Drop existing connections, use a single identity per server |
| 1311 | 0x8007051F | No logon servers available | Domain controller unreachable; check DNS and time sync |
| 1322 | 0x8007052A | Logon batch logon failure — local security policy denies logon as service / batch / interactive | Grant the SeBatchLogonRight or SeInteractiveLogonRight in gpedit.msc |
| 1326 | 0x80070526 | Logon failure: unknown user name or bad password | Align service identity, fix share / NTFS ACL, NTLMv1 disabled |
| 1327 | 0x80070527 | Account restriction | Check logon hours and "Logon To…" constraint |
| 1330 | 0x8007052A | Password expired | Set password never expires on service account or rotate in maintenance window |
| 1355 | 0x8007054B | The specified domain either does not exist or could not be contacted | DNS / VPN / domain trust issue |
| 1789 | 0x800706FD | The trust relationship between the primary domain and the trusted domain failed | Domain trust / secure channel; reset machine account password |
| 6118 | 0x800717FE | The list of servers for this workgroup is not currently available | NetBIOS disabled, browser service not running, network discovery off |
7. Diagnostic Procedure
-
Confirm DNS resolution. From a command prompt on the WinCC host, run
nslookup SERVER. The hostname must resolve to a reachable address. Repeat with the FQDNnslookup SERVER.contoso.localif the server is domain-joined. -
Test the path from an interactive session. Open Run, paste
\\SERVER\ALARMS. If Windows Explorer opens the share, the network and ACL are working at user level. If you receive a credential prompt that succeeds for the operator, the network is fine and the WinCC identity is the variable. -
Test the path from the service identity. From an elevated command prompt run
whoamito confirm your administrative context, then runsc.exe start CCAlgfollowed by a scripted cmd /c dir \\\SERVER\ALARMS under the service account using psexec -u svc-wincc -p <pw> cmd. The output captures the exact error the script will see. - Inspect the security event log on the file server. Open eventvwr.msc on SERVER, navigate to Windows Logs > Security, filter by event ID 4625 (failed logon) and 5140 (network share accessed). The failure reason code in the 4625 event is the most reliable source of truth for the underlying cause.
- Verify SMB signing and NTLM policy. Group Policy path: Computer Configuration > Policies > Windows Settings > Security Settings > Local Policies > Security Options > Network security: LAN Manager authentication level. If this is set to Send NTLMv2 response only / refuse LM & NTLM, but the file server still accepts NTLMv1 only, the call fails with 1326. Microsoft documents the values in the Microsoft Learn reference for the underlying SMB stack.
- Confirm the firewall allows TCP 445 inbound on the file server. On Windows Server 2022 the default profile is the same as Windows 10/11: block inbound by default. The file server role opens the exception; check wf.msc > Inbound Rules > File and Printer Sharing (SMB-In).
- Trace the call with Process Monitor. Filter for scriptrt.exe and WNetAddConnection2 / CreateFileW with paths matching \\SERVER\ALARMS. The stack column will show exactly which authentication package the client is requesting (NTLM, Kerberos, NEGOEX) and which the server is negotiating.
8. Resolution Procedure
- On SERVER, create a share, for example ALARMS, rooted at D:\ALARMS. Under Share Permissions grant Read to the group SCADA-File-Read and remove Everyone. Under Security on the same folder, verify SCADA-File-Read also has Read & execute, List folder contents, and Read in the NTFS ACL.
- Create the domain user svc-wincc with the properties listed in section 4.2 and add it to the SCADA-File-Read domain group.
- On the WinCC host, open services.msc, change the logon of CCAlg, CCArchive, and ScriptRT to svc-wincc. Provide the password when prompted. Restart each service.
- On the WinCC host, run
gpresult /h gp.htmland confirm that the new service account inherits no policy that denies network logon. The Microsoft reference for the security baseline is the Connect to a Remote Computer documentation, which enumerates the user rights required for cross-machine file access. - Open WinCC Explorer, open the picture, edit the script and change the path from
\\\\SERVER\D$\\ALARMS\\Alarms.txtto\\\\SERVER\\ALARMS\\Alarms.txt. - Test from the WinCC runtime as an operator.
9. Verification
After applying the fix, validate each layer independently.
- From an elevated prompt on the WinCC host, run
psexec -u svc-wincc cmdand thentype \\\SERVER\ALARMS\Alarms.txt. If the file contents print, the share is reachable under the correct identity. - From the WinCC runtime, click the button. NotePad opens, displaying the file. No dialog.
- Capture the Security log on SERVER for the test window. There must be exactly one 4624 (successful logon) and one 5140 (network share accessed) event, both showing the svc-wincc account as the user.
- Run the script under a second operator account to confirm group-based authorisation works, then under a third account that is not a member of SCADA-File-Read to confirm the deny path is enforced.
10. Operational Hardening
Once the immediate failure is resolved, apply the following practices so the configuration stays healthy.
-
Disable administrative shares on the file server. Set
HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters\AutoShareServer = 0and reboot. This forces every consumer to go through a named share, making ACLs auditable. - Document the share name and the calling identity. Place a one-page reference in the WinCC project documentation. The reference must list the UNC, the share ACL, the NTFS ACL, and the service account.
- Rotate the service account password via a Group Policy Preferred Password. Do not let the password expire silently. If the account is set to Password never expires, the rotation must still happen on a documented schedule.
- Capture the credential in the WinCC backup. When the WinCC project is backed up using SIMATIC WinCC / PCS 7 backup tools, store the service account in the same secure enclave so the system can be rebuilt without losing the identity chain.
- Watch the Security log. 4625 with status 0xC000006A (bad password) or 0xC0000234 (account locked out) appearing on the file server means the WinCC service is using the wrong credential. Alert on this.
Why does the local path work but the UNC path fails with "Logon failure: unknown user name or bad password"?
The local path does not require authentication against another machine, so the WinCC process identity is irrelevant. The UNC path triggers an SMB session, which requires the WinCC process to authenticate against the file server under the identity it is running with. If that identity has no account on the file server or has the wrong password, the SMB stack returns 1326 ERROR_LOGON_FAILURE. Fix by running the WinCC service under a domain account that is granted Read on the share and on the NTFS ACL.
Should I use \\SERVER\D$ or a named share?
Use a named share. The D$ administrative share requires the calling identity to be a member of the file server's local Administrators group, which is a privilege escalation risk. Administrative shares are also disabled on hardened Windows Server installations. Create a dedicated share, for example ALARMS, and grant the service account Read on the share and on the NTFS ACL.
Can I use a local user with the same username and password on both machines instead of a domain account?
Yes, in a non-domain test cell. The two machines must have a local account with identical username and identical password for the NTLM hash to match. This configuration does not scale, is fragile against password rotation, and is not supported for multi-server topologies. Use a domain service account for any production system.
The script works when the operator is logged in interactively but fails when WinCC runs as a service. Why?
When an operator clicks a button on a WinCC picture, the script runs in the process that hosts the picture, which is the WinCC runtime service, not the operator's interactive session. The operator's mapped drives, credentials, and SMB tickets are not inherited by the service process. The script must be written to work under the service identity, and the service identity must be granted the share access.
What is the recommended alternative to ProgramExecute for opening remote files from a WinCC script?
For reading file content into tags, use the WinCC file system object, the CSV provider, or a custom OLE DB connector. For launching an external editor, use the Shell.Application COM object (ShellExecute) under a known service identity, or use Start-Process from a PowerShell launcher running under that identity. Avoid relying on the interactive operator's credentials when the launch originates from a runtime service.