You cannot load only the front panel of a LabVIEW VI. Open VI Reference loads the VI together with its statically linked hierarchy: subVIs, typedefs, classes, XControls and libraries. A plugin selector that opens every candidate VI to check for two named input controls and three named indicators pays the full load cost for every file. When a VI carries several classes, that cost can reach a minute or more per plugin. The fix is to stop using a full load as the validation step. Measure the load, then move the check to data you can read cheaply: a naming rule, a library tag, or a manifest built ahead of time.
Time the plugin load before changing anything
A large application of a couple of thousand VIs can load in a few seconds through one Open VI Reference call from a splash loader. If a single plugin takes minutes, the size of the plugin is often not the only cause. Rule out the fixable causes first:
- Open one slow plugin by hand and watch the loading dialog. If it shows LabVIEW searching for files, a dependency path is broken. LabVIEW is walking its search paths and every miss adds time.
- Check whether saving the VI is enabled after it loads, even though you changed nothing. If so, the VI or its dependencies were saved in an older version or against moved dependencies, and LabVIEW recompiles or relinks them on every load.
- Count the classes in the plugin's hierarchy. Loading any member of a LabVIEW class loads the whole class and all its member VIs, so one class reference can pull in far more code than the diagram suggests.
- Time
Open VI Referencealone with a millisecond tick count before and after the call, for each plugin.
Check: after you fix the search paths and mass compile the plugin folder, time the load again. If the time drops to seconds, the problem was relinking or searching, and your existing validator may be fast enough. If class-heavy plugins still take close to a minute, continue.
Drop the quick fixes that cannot read control labels
Two shortcuts come up first. Neither answers "does this panel have these five terminals with these labels and types?"
| Attempted fix | What it returns | Why it fails for plugin validation |
|---|---|---|
| Load only the front panel | Nothing. No supported call does this. | The panel, diagram and link table live in one VI file. Opening a reference resolves the links. |
Read Link Info (private scripting method) |
The dependency list: subVIs, typedefs, classes, XControls, libraries | Shows what the VI uses, not what is on its panel. Control labels and terminal roles are absent. |
| Strictly typed VI reference | A reference that loads only if the connector pane matches | Still loads the whole hierarchy before it rejects a mismatch, so the cost is the same. |
| Open, check, close | A correct answer | Correct, but it pays the full load time on every candidate every time the selector runs. |
Read Link Info can still work as a pre-filter in one case. Make the plugin interface a strict typedef, for example a typedef cluster or typedef controls used only by plugins. Plugins that use it will list that typedef in their link info, and anything without it is rejected without a load. This does not confirm labels, counts or input/output direction. The method is also private scripting, so its behaviour can change between LabVIEW versions. Treat it as a filter only.
Check: run Read Link Info on one known-good plugin and one non-plugin VI. Confirm the interface typedef shows up only in the plugin before you rely on the filter.
Write the plugin contract down as data
Every later step compares against the same contract, so define it once, in one place. Here the contract is two controls and three indicators, each with a fixed label and data type. Store it as a constant array of records that both the validator and the build tool read:
PluginContract[] =
{ Label: "<input label 1>", Role: Control, ClassName: "<expected class>" }
{ Label: "<input label 2>", Role: Control, ClassName: "<expected class>" }
{ Label: "<output label 1>", Role: Indicator, ClassName: "<expected class>" }
{ Label: "<output label 2>", Role: Indicator, ClassName: "<expected class>" }
{ Label: "<output label 3>", Role: Indicator, ClassName: "<expected class>" }
ContractVersion = <integer, bump on any change>
Fill in the class names from a known-good plugin: read ClassName from each panel object instead of typing them from memory. Label matching is exact text, so a trailing space or a case change fails the match.
Check: run the full check (next section) against a known-good plugin and a deliberately broken copy with one label renamed. The good one passes and the broken one fails.
Restore the selector tonight with a cached full check
This is the temporary restore. Keep the correct but slow check, but run it only when a plugin file changes:
- For each
.viin the plugin folder, read the file path, size and modification time. - Look the path up in a cache file (INI, XML or JSON beside the plugins, or in the user data folder).
- If the size and modification time match the cached entry, and the cached contract version equals the current one, use the cached pass/fail result and do not load the VI.
- Otherwise run
Open VI Reference, read theFront Panelproperty, thenPanel.Controls[]. For each object, readLabel.Text,ClassNameand whether it is an indicator, and compare against the contract. - Write the result to the cache and close the reference so the hierarchy can unload.
The first scan is still slow. After that the selector opens only new or edited plugins. If users usually pick the plugin that was just validated, you can hold that one reference open instead of closing it, so the real load is instant. Keep only one held reference, or memory grows with every class-heavy plugin.
Check: run the selector twice without touching the plugin folder. The second run should open zero VI references. Log the count to confirm. Touch one plugin file and confirm only that file is reopened.
Make the plugin folder self-describing by name
The first permanent fix costs no load at all: identify plugins by file name or folder. Put valid plugins in a dedicated folder, or give them a fixed prefix or suffix. The selector then lists matching files and loads only the one the user picks.
- This works when you control who adds files to the folder.
- A name proves intent, not the connector. Validate the chosen plugin after it loads, and show a clear error if its panel does not match the contract.
- Combine this with the cache so a renamed non-plugin cannot fail again on every run.
Check: drop an unrelated VI into the plugin folder without the naming rule. It must not appear in the list, and no reference to it may be opened.
Tag plugins through an lvlib instead of loading the VI
The stronger permanent fix is to require every plugin to belong to a LabVIEW project library (.lvlib) and mark the library with a user tag. Opening a library reference loads the library definition, not every member VI. That is different from a class, which loads all its members. The selector can read the tag without touching the heavy hierarchy behind the plugin VI.
- Define the tag contents: plugin flag, contract version, and the name of the entry-point VI inside the library.
- Write the tag with a scripting tool when the plugin is built or published. Do not set it by hand.
- In the selector, list the
.lvlibfiles, open each library reference, read the tag, and close the reference. - Show only libraries whose tag matches the current contract version. Load the entry-point VI only after the user picks it.
Library tag access goes through the library class methods that LabVIEW exposes via VI Scripting. Confirm which tag methods your LabVIEW version exposes, and whether scripting access must be enabled in Tools > Options, before you commit the design.
Check: watch memory and load time while the selector scans. Opening the library references should show no subVI or class loading, and a class-heavy plugin should now list in the time it takes to read a small file.
Validate the panel at publish time, not at selection time
A tag or manifest only helps if something checked the panel honestly. Move the full Controls[] check from the running selector into the tool that publishes plugins:
- The developer runs the publish tool on a new or edited plugin.
- The tool opens the VI once and runs the contract check from the earlier section.
- On a pass, it writes the lvlib tag or a manifest entry (path, contract version, pass). On a fail, it refuses to publish and lists the missing or mistyped terminals.
The slow load happens once per plugin revision, on a developer machine, instead of on every operator launch.
Check: publish a plugin with one indicator changed to a control. The tool must reject it and name the terminal.
Prove the selector end to end
- Fill the plugin folder with known-good plugins (including the slowest class-heavy one), one broken plugin, and one unrelated VI.
- Start the selector cold, right after launching LabVIEW or the built application. Confirm that only the valid plugins appear, the list comes up without loading any plugin hierarchy, and the logged count of opened VI references is zero.
- Pick the heaviest plugin. Confirm it loads, passes the runtime contract check, and runs.
- Edit one plugin without republishing it. Confirm the selector either rejects it (stale tag or manifest) or revalidates only that file (cache path).
- Bump the contract version. Confirm every plugin drops out until it is republished.
FAQ
Can I open a LabVIEW VI front panel without loading its subVIs?
No. Open VI Reference resolves and loads the VI's static dependency hierarchy, including classes and typedefs. Read the panel through Front Panel and Panel.Controls[] only after a full load, or avoid the load with a naming rule, library tag or manifest.
Does Read Link Info show which controls are on a VI front panel?
No. It returns dependencies (subVIs, typedefs, classes, XControls, libraries), not control labels. If your plugin interface is a unique strict typedef, the typedef's presence in the list works as a pre-filter. You still need a panel check to confirm labels, count and direction.
Does loading a VI inside an lvlib load every VI in the library?
No. A project library loads its definition without loading every member VI. A LabVIEW class loads all its members when any member loads, which is why class-heavy plugins are slow and why lvlib tags make a cheap validation marker.
Can I speed up Open VI Reference on a single slow VI?
Yes, if the delay comes from LabVIEW searching for moved dependencies or recompiling VIs saved in an older version. Fix the paths and mass compile the plugin folder. If the time is still close to a minute, the delay is real hierarchy size and only avoiding the load helps.
When should I stop and contact NI support about plugin load times?
Escalate if a plugin still takes minutes to load after the search paths are fixed and the folder is mass compiled, or if the library tag or Read Link Info scripting methods behave differently after a LabVIEW upgrade. Send NI support the LabVIEW version, the timed load results, and a reduced plugin that reproduces the delay.