Where does the openURL request stop?
Follow the packet. A button or event script builds a string and hands it to system.net.openURL. That call runs in the Vision client JVM on the operator workstation, not on the Gateway. The client passes the URL to the operating system. The OS resolves it to a file on the SMB share and launches the viewer registered for the extension. A failure at any hop looks the same to the operator: nothing opens.
| Hop | Component | Job | Failure signature |
|---|---|---|---|
| 1 | Client script | Builds the path and URL string | Wrong prefix, raw spaces, bad backslash escapes |
| 2 | system.net.openURL |
Parses the string as a URL and hands it to the OS | Malformed URL rejected; nothing launches |
| 3 | Client OS shell | Maps the file: URL to a UNC path and picks an application |
No file association for the extension |
| 4 | SMB to srv-01
|
Reads the file with the logged-in Windows user's credentials | Name resolution, reachability, or access denied |
| 5 | Viewer application | Opens the file | Viewer error, corrupt file |
In the failing setup, system.file.fileExists(f) returned true for //srv-01/share/_NGB Work Orders/RS20141120-04/Attachments/VesselInventoryError.png. That proves hops 1 and 4 on the filesystem side: the client resolves srv-01, reaches the share, and can read the directory. The same code worked on 7.7 and stopped after the upgrade to 7.8 with no change to the share. The request dies at hop 2.
Check: add print fileToOpen before the call and read the client console output. Record the exact string being passed. For the original code it is file://///srv-01/share/_NGB Work Orders/..., which has five slashes and literal spaces.
Can the client machine reach the share at all?
Layer one first. Confirm the path from the workstation that runs the client, under the Windows account the operator logs in with, before you touch URL syntax. A Designer on an engineering laptop with domain-admin rights proves nothing about a locked-down HMI panel.
| Test (on the client PC) | Pass | Fail means |
|---|---|---|
ping srv-01 |
Name resolves, replies | DNS/NetBIOS or routing problem |
Open \\srv-01\share in Explorer |
Folder lists | SMB blocked or no share permission |
system.file.fileExists(f) with the raw, unencoded path |
True |
Path typo or client-side access problem |
Check: all three pass. If fileExists returns false, fix the network path or permissions first. No URL encoding will open a file the client cannot read.
What URL string does 7.8 accept?
A URL cannot contain a literal space. URI syntax requires reserved and unsafe characters to be percent-encoded, and a space becomes %20. Ignition 7.7 tolerated the raw spaces in _NGB Work Orders. Ignition 7.8 parses the argument strictly, so the call is rejected before the OS ever sees it. The prefix also matters. In file://host/path form, srv-01 sits in the host position. A drive-letter path needs an empty host, which is written as three slashes.
| Filesystem path | Prefix | URL passed to openURL
|
|---|---|---|
//srv-01/share/_NGB Work Orders/.../VesselInventoryError.png (UNC) |
file: |
file://srv-01/share/_NGB%20Work%20Orders/.../VesselInventoryError.png |
S:/Work Orders/x.png (mapped drive) |
file:/// |
file:///S:/Work%20Orders/x.png |
C:/temp/x.png (local) |
file:/// |
file:///C:/temp/x.png |
Check: call a hard-coded, known-good literal from a test button on the client:
system.net.openURL('file://srv-01/share/_NGB%20Work%20Orders/RS20141120-04/Attachments/VesselInventoryError.png')
If the image opens, hops 2 through 5 work. What remains is to generate that string from any path.
How do I build the URL in script?
Put the conversion in a project script library function so every button uses one implementation. The function normalises the separators, picks the prefix, encodes the path, and logs the result.
def openNetworkFile(filePath):
# Normalise Windows separators to forward slashes
path = filePath.replace('\\', '/')
# Drive letter (C:/, S:/) -> file:/// UNC (//server/share) -> file:
if ':' in path:
prefix = 'file:///'
else:
prefix = 'file:'
# Encode '%' first so later escapes are not double-encoded,
# then '#' (fragment marker) and spaces
path = path.replace('%', '%25').replace('#', '%23').replace(' ', '%20')
url = prefix + path
print url
system.net.openURL(url)
Call it from the button with the raw path. Keep the existence test on the unencoded filesystem path:
f = '//srv-01/share/_NGB Work Orders/RS20141120-04/Attachments/VesselInventoryError.png'
if system.file.fileExists(f):
project.util.openNetworkFile(f)
else:
system.gui.warningBox('File not found: ' + f)
Adjust the project.util path to wherever the function lives in your project library. If filenames can contain other reserved characters, replace the chained replace() calls with urllib.quote(path, '/:') after import urllib. That call encodes everything except the separators and the drive colon.
Check: the printed URL for the test file matches the known-good literal from the previous section character for character.
Which path details still break the call?
| Symptom | Cause | Fix |
|---|---|---|
| Path garbled before it reaches the function | Backslashes in a Python literal are escape sequences (\s, \f, \n) |
Use a raw string r'\\srv-01\share\...' or write forward slashes |
fileExists returns false after the upgrade code change |
Encoded path passed to fileExists
|
Test the raw path; encode only the URL |
File with % or # in its name fails |
Unencoded reserved characters; # truncates the path as a fragment |
Encode % to %25 first, then # to %23
|
| Works on one client, not another | Drive letter mapped differently per PC | Store and pass UNC paths, not mapped drives |
| Works for engineers, not operators | SMB share or NTFS permission for the operator account | Grant read access to the account the client runs under |
| No error, nothing opens | No application associated with the extension on that client | Set the file association in Windows on the client |
| Five slashes in the logged URL |
file:/// prefixed to a //server path |
Use file: for UNC paths |
Check: run the function against a test file whose name contains a space, a #, and a % on the same share. It must open without edits to the calling script.
How do I verify the fix end to end?
- Publish the project and restart or update the Vision client on an operator workstation. Test on the operator workstation, not in the Designer.
- Log in with the operator Windows account and confirm
\\srv-01\shareopens in Explorer. - Press the button for the original work-order attachment. Read the printed URL in the client console and confirm it starts with
file://srv-01/and contains_NGB%20Work%20Orders. - Confirm
VesselInventoryError.pngopens in the registered image viewer. - Repeat with a mapped-drive path and confirm the printed URL starts with
file:///followed by the drive letter. - Repeat with a nonexistent filename and confirm the warning box appears and no
openURLcall is logged. - Open the same attachment from a second client PC with a different drive-letter mapping and confirm the UNC path opens identically on both.
FAQ
How do I open a UNC network file with system.net.openURL in Ignition 7.8?
Convert backslashes to forward slashes, prefix the //server/share/... path with file:, and replace spaces with %20. The result is file://srv-01/share/_NGB%20Work%20Orders/....
Why did system.net.openURL stop working after upgrading from 7.7 to 7.8?
Ignition 7.8 parses the argument as a strict URL, and literal spaces are illegal in a URL. Paths that 7.7 tolerated, such as file:/// plus a UNC path with raw spaces, are rejected before the OS receives them.
How do I choose between file: and file:/// in Ignition scripts?
Use file:/// for local or mapped-drive paths that contain a drive colon, such as C:/ or S:/. Use file: for UNC paths that already begin with //server, so the server lands in the URL host position.
How do I handle backslash paths like \\server\share in an Ignition script?
Write the literal as a raw string, such as r'\\srv-01\share\file.png', or use forward slashes. Then convert with replace('\\', '/') before building the URL, because Python treats unescaped backslashes as escape sequences.
How do I confirm the openURL fix works on operator clients?
Run the button on an operator workstation under the operator Windows account and check that the console shows the encoded file: URL. Confirm the file opens, then repeat on a second client PC to rule out drive-mapping differences.