Custom Property Loader Plugins in TestStand

Update 30/10/2018

This was going to be part of a series but unfortunately, as mentioned below, there was a lack of available documentation and I ended up implementing a workaround – it was a much simpler solution that could be easily tested. I created an action step which pulled the limits/parameters from the database and wrote them to a temporary CSV file which is then loaded by a Property Loader step. I’d probably only suggest implementing custom plugins at this stage if you were releasing/selling an addon/customisation for TestStand where it would make the time investment worthwhile. Of course, hopefully in TS2017 the documentation will be available to make the process much easier.


In this series of blog posts, I’m going to be talking about how to create a Custom Property Loader Plugin for TestStand using LabVIEW.

I have a custom database schema that doesn’t follow the NI database format that the built-in property loader plugin supports. We have separate tables for limits/test configuration parameters and options for product/test specific limits/parameters. In the last few years, NI has changed aspects of the TestStand Engine to allow more customisation of the various aspects by the use of plugins (e.g. process model plugins, report generation, property loader plugins). The advantage of using a custom property loader plugin is that it allows us to use our custom limits/parameters database but also use the other built-in options as an alternative (e.g. for off-site use at a contract manufacturer without access to the database).

Unfortunately, I couldn’t find much documentation on the subject (NI says that the documentation is coming for TestStand 2017) so figured I’d suffer through the hard work and post it so you know what to expect if you intend on creating custom property loader plugins for TestStand.

For the first part of the series, I’ll start by giving an overview of what a property loader is (and what it does), why you should use it, how to create a custom plugin from the template and give an overview/reference of the VIs / ActiveX objects that make up a custom property loader plugin. In subsequent parts, I’ll be building up my plugin by modifying the VIs to talk to my custom database schema (and the challenges that may come along with it).

Our custom property loader plugin will be talking to a database – but the process should be similar for files – just replace any instance where I’m referencing a database with your custom file IO.

For reference, I’m running TestStand 2016 SP1 and LabVIEW 2017.

Loading Properties in TestStand

Before going into the details of creating a custom property loader plugin (CPLP?! CPP?!) I wanted to just give a quick overview of the various components/mechanisms of loading properties in TestStand.

The main use case for a property loader is to load your test limits and/or test parameters from a file or database at run-time. This gives you the following benefits:

  • You can modify/update limits without modifying the sequence files (of course, you need an appropriate change management system)
  • All of the limits/parameters are in a single location (e.g. a file/database table rather than having to check individual sequences/steps) – this makes checking/validating/updating the limits/parameters easier
  • You can load different sets of limits depending on certain conditions – by specifying the file by expression, you can use different sets of limits/parameters depending on the UUT being tested (e.g. similar products in the same family but with different characteristics)
  • Using a centralised database or network-shared file for the properties means that all test stations use the same limits for testing

Natively, TestStand supports comma-separated (.csv), Excel and tab-delimited text (.txt) files and loading properties from an NI TestStand database schema. There’s plenty of information online and in the TestStand training materials about using the built-in plugins (e.g. here, here and here).

The property loader can import any property to just about any TestStand component (that has properties) – the most useful ones are step properties (e.g. to set limits) and sequence variables (e.g. sequence/sub-sequence Locals, StationGlobals etc.). You can also use aliases so that your parameters/limits have sensible names and then these are automatically mapped to the appropriate steps/properties in your sequence.

There are two ways to use property loaders – a property loader step in a test sequence and using the import/export properties dialog in the TestStand tools menu.

It is important to mention this because our custom property loader plugin will not only load and apply properties from the database, but it should also work with the import/export properties dialog as well.

Property Loader Step

The Property Loader Step in TestStand allows you to load properties at sequence/execution run-time by dropping a Property Loader step into your sequence and configuring it on the Step Settings and Source Settings panes of the Step Settings.

Import/Export Properties Dialog

You can also use the import/export properties dialog to manually import/export properties to/from a property loader source. This is useful for generating the initial source data in the correct format (e.g. set the properties in the TestStand environment, export and then load the data in the property loader step) and for verifying the source data. You also use the Export function of the dialog to generate an aliases file (.pla).

As with the Property Loader Step type, you can select the Source for the properties and configure whether to load all of the properties, or just select properties (using the Property Selector pane).

Creating A Custom Property Loader Plugin

The only documentation I could find on creating custom property loader plugins was this small snippet of information which says to copy one of the existing template plugins as the starting point and go from there. So I guess we’ll just dive in then…

Duplicating the Template Plugin

Shipping with TestStand 2016 SP1 is a selection of sample plugins for various programming languages/environments (CVI, .NET, VisualStudio and LabVIEW). You can find these in <TestStand Install Directory>\Components\PropertyLoader\Templates (i.e. C:\Program Files (x86)\National Instruments\TestStand 2016\Components\PropertyLoader\Templates).

The documentation says to copy the template plugin to <TestStand Public>\Components\PropertyLoader\<YourPluginName> directory – initially I couldn’t get the plugin to load following these steps and after a support request with NI it seems that you have to copy and rename the template .llb file to <TestStand Public>\Components\PropertyLoader\ (i.e. C:\Users\Public\Documents\National Instruments\TestStand 2016 (32-bit)\Components\PropertyLoader\MyPlugin.llb) rather than having it reside in a sub-folder. The PropertyLoader folder in <TestStand Public>\Components probably won’t exist if this is your first attempt at a custom plugin – so you’ll need to create it.

You’ll end up with something like this:

The next step is to configure our new plugin by modifying the inside our fresh plugin .llb file:

Modifying the plugin information for the custom property loader plugin

The VIs themselves are reasonably well documented (most of them are empty stubs though) – here we need to set up the basic information (some fields only apply when loading files e.g. ‘extension’) for TestStand to identify it. You need to change the ID (by default it’s a GUID but I think you can use anything as long as it’s going to be unique to your plugin).

The ‘Type’ field has the following options which are fairly self-explanatory:

  • SourceType_Database: When you choose this, the Step Settings for the property loader step allows you to specify/configure a database connection
  • SourceType_File: As above, but it prompts you for a file path to the file containing your properties
  • SourceType_Custom: I tried to set the enum to SourceType_Custom to see what happened but it just produced an error in TestStand (see below) so I’m not sure if there’s something else that needs to be configured/set first to get this one to work. I guess you’d use this for anything that isn’t a file or a database? Ideas on a postcard please!

That’s OK – I didn’t want to create a SourceType_Custom plugin anyway…

After populating the fields and launching TestStand, you can then drop a Property Loader step into your sequence and you should see your newly created plugin in the Source Type drop-down:

‘Hacking TestStand by Code Injection’ – Available at all good bookstores soon!

Of course, at this point it doesn’t do anything but we’ve at least managed to get it to load and register the plugin. Time for a beer (or other beverage of your choosing)! Next we’ll take a deeper look at what’s inside the template plugin.

Exploring the Template Plugin

Opening up the .llb of the plugin we’ve just created, we find the following VIs:

Contents of a LabVIEW Property Loader Plugin

I’ve already discussed the which sets the metadata/information about the plugin that TestStand uses to populate the plugin in the source type drop down box.

Let’s take a look at the VIs in the template plugin and their functionality…

Custom Property Loader Plugin VIs

Name Description If ‘SupportsBrowseSource’ is set in OverrideOptions (see below), this VI is called when the user clicks the ‘Browse Source’ button – for files this could launch a file dialog or for a database it could be to select a specific set of tables.

Called when you select the ‘Configure’ button on ‘Plugin Options’ (see below). You could use this VI to launch a dialog where the user can set/configure any plugin specific options for import/export. This is similar to creating a LabVIEW dialog for configuring a custom step type. Called when the user hits the ‘Help’ button in ‘Plugin Options’ (see description). Used when a property loader ‘Export’ is called from the import/export dialog – this is the main VI that exports the current property values back to the property loader source (e.g. file/database). If ‘OverrideImportExportSummary’ is set, then you can also return a custom summary text to display the status of the export operation. The reverse of (see below) – if you have the ‘OverrideAlias’ set then this can be used to perform an export of the aliases to a custom aliases format. By default, you configure aliases from the Import/Export Properties dialog and these are then automatically exported (as an XML .pla file) when you perform the export. Called before to read the source and retrieve only the property loader groups information and the properties within that group. This data is used when importing all of the source data (so the plugin knows which properties to load i.e. all of them), determining if a property exists in the source, populating the property selector (for the import/export dialog) and for specifying the properties for the Import operation. Used when a property loader ‘Import’ is called (either through property loader step or the import/export dialog) – this is the main VI that retrieves the properties from the file/database to apply them to the steps/sequence properties. If ‘OverrideImportExportSummary’ is set, then you can also return a custom summary text to display the status of the import operation. If ‘OverrideAlias’ is set in OverrideOptions (see below), this VI allows you to write custom behaviour for loading the alias names. Aliases allow you to match up variable/parameter names in your property loader source with their matching counterpart in the test sequence (e.g. variable/property name) – there’s documentation and an example of using aliases here. Overriding the default functionality allows you to load/configure aliases as part of your custom plugin (e.g. generate them dynamically or from your property source), rather than specifying them in an aliases file (.pla). Used to set override flags/options which control certain options for the plugin (e.g. to allow the user to view the source data and browse for the source). The list of options/overrides are detailed in the ActiveX reference below. Defines the basic metadata about the plugin when it’s loaded into TestStand (e.g. name, description, type, plugin ID). Creates/initialises the available plugin specific options. Generates a summary text of the plugin specific options as shown in ‘Plugin Options’ (see description). Specifies the number of different source types that the plugin supports. I’m not quite sure what this means and the template plugin returns 1 (i.e. the plugin supports one source type). I’m not sure if this means that a single plugin can support multiple types (but it’s not obvious how to specify them) – maybe this is reserved for future use? Called by the Sequence Analyser to allow the creation of a custom VI to check the status of the source during sequence analysis. This could be to check for a correctly configured database connection, check properties are available etc. and return an error if the analysis fails. Used to launch a dialog to ‘browse’ the source data (e.g. view the source file, browse database tables).

Custom Property Loader Plugin ActiveX Components

The VIs all interact using ActiveX methods/properties (as with any other custom LabVIEW components for TestStand), here is a brief overview of the main ones that are used in the VIs.

Name Description Properties Methods
PropertyLoader.PropertyLoaderContext A reference to the instance of the property loader containing generic configuration parameters for the instance and references to the TS Engine and Sequence (i.e. the location of the PropertyLoader). AliasLocation
PluginSpecificOptions (PropertyObject) PropertyObject containing the plugin specific options. (See TS.PropertyObject) (See TS.PropertyObject)
PropertyLoader.SequenceFileLoader Contains the list of properties to import which are then updated with the property objects once loaded. AliasNames
PropertyLoader.ImportOptions Contains the user-configured options for the import operation. ImportAllDataFromSource
PropertyLoader.ImportPropertyItems Container for the list of properties in the property source. Count Clear
PropertyLoader.PropertySourceGroups Container for the list of groups in the property source. Count Clear
PropertyLoader.AliasNames Contains the aliases used for the import/export operation – used when overriding the default plugin alias functionality (using OverrideAlias). Count Clear
PropertyLoader.OverrideOptions Contains the options for overriding/enabling certain functionality for the custom plugin. OverrideAlias
PropertyLoader.PropertyLoaderPluginInfo Contains the basic metadata about the plugin. Description
PropertyLoader.ExportOptions Contains options for exporting properties to the source. StepIdUniqueLookup N/A


That’s enough for Part One. I’ve covered an overview of how Property Loaders work, why you would want to create a custom plugin and how to create your very own custom property plugin and load it into TestStand. I’ve also provided some reference material about the VIs and ActiveX objects that make up a custom plugin. In Part 2, I’ll begin customising the VIs to work with a custom database schema.

MediaMongrels Ltd Custom TestStand Solutions

If you’re looking for a bespoke test system and are considering using TestStand, why not get in touch and see if MediaMongrels Ltd can help. We are an NI Alliance Partner with Certified TestStand Developers and we have experience of architecting test systems from the ground up (including custom process models, Operator UIs, custom database recording) to provide flexible and configurable test frameworks for your component and system tests.

Malleables VIs: Practical Example Part 2 – Malleable Class Adaptation & Practical Application

This is the second of a two part post about the use of Malleable VIs in a practical project – rewriting a test system to use TestStand. In Part One, I introduced the project and the decision to use LabVIEW OO and Hardware Abstraction Layers to allow an easy switch between Simulated and Physical hardware in the test sequence.

In this part, I will discuss the implementation in more detail and how I am using the Class Adaptation feature of Malleable VIs. Class Adaptation allows me to create a malleable VI that can act on unrelated classes (i.e. no inheritance between them). I believe in Computer Science terms, this qualifies as some sort of Mixin.

Read more

Malleables VIs: Practical Example Part 1 – OO Hardware Interfaces for LabVIEW/TestStand


In my first LabVIEW-related blog post, I introduced Malleable VIs, a new feature in LabVIEW 2017 allows the creation of generic VIs that can adapt to different data types on the connector pane.

In this two part post, I wanted to give a practical example from a current project I am working on to show some of the power of Malleable VIs. Part One (you are here!), will introduce the project and how I am using LabVIEW Classes (OO) to create Hardware Abstraction Layers (HALs) in LabVIEW for use with a TestStand test system. Part Two delves further into the implementation and show how I am using the Class Adaptation feature of Malleable VIs in the development of the test system.

Read more

NI Event: Implementing Industrial Internet of Things (IIoT)

On Wednesday 28th March I attended the ‘Implementing the Industrial Internet of Things’ event organised by National Instruments.  The aim of event was to give an overview of the technologies and considerations needed to implement the Industrial Internet of Things (IIoT).

The event took place at the fantastic and very modern looking Advanced Manufacturing Training Centre in Coventry. There was a very varied group of attendees at the event including Engineers, NI Alliance Partners (such as MediaMongrels Ltd), Academics, IT Professionals and even Market Analysts, all looking to learn more about the future of connected industry.

Content Overview

One of the early slides highlighted a couple of interesting statistics:

50 billion connected devices by 2020 – Cisco

~50% of connected devices deployed between 2015 and 2025 will be industrial – IHS Markit

This was followed by an overview of the various systems and components that make up an IIoT solution, as shown in the slide below:

© National Instruments

The event then was broken down into various presentations covering the following topics and showing how they fit within the IIoT  ecosystem:

  • Data Acquisition (hardware selection, sensor placement, sample rates, FPGA for high-speed acquisition, adequately describe data e.g. metadata)
  • Processing and Feature Extraction (where to process data? edge node, on-premises server or cloud?)
  • Control (using FPGA or RT for real-time control)
  • Communication (synchronisation of data, Time Sensitive Networking – technology allowing deterministic communication between critical machines/processes)
  • Security (securing edge nodes, use secure protocols e.g. https, use detection as well as protection)
  • Deployment (how to deploy to multiple systems? demo of NI SystemLink)
  • Data Management (how much data to store? how long for? database technologies)
  • Analytics & Machine Learning (use of process experts still relevant for training machine learning algorithms)
  • Visualisation (e.g. real-time data dashboards, augmented reality)

Of course, there is nothing new about these components individually, it is the bringing of them together to allow better business and engineering decisions to be made faster that I feel makes up the core idea of the Industrial Internet of Things. The benefits could be a reduction in downtime (e.g. through predictive maintenance) or improvements in productivity and quality (discovering and resolving inefficiencies).

As a National Instruments event, they were keen to show how their products and services can be used to deliver IIoT solutions (e.g. using an NI CompactRIO as an edge node, DIAdem for Data Management) but the event didn’t go into specifics or detailed implementation – it was more to provide an overview of the various technologies and to highlight some IIoT success stories.

It is clear to see that National Instruments is putting a lot of investment into IIoT – from their IIoT Lab in Austin, IIoT products/services (e.g. InsightCM, SystemLink) to wider collaboration with various related technologies (e.g. Augmented Reality, Industrial Networking).


Overall, it was a good opportunity to network with like-minded professionals and interesting to see how previous projects fit within the ‘IIoT’ remit. I also learnt more about some of the new technologies/products that will help deliver IIoT solutions in the future (e.g. Time Sensitive Networking, NI SystemLink).

You can find the presentations from the event here.

MediaMongrels Ltd. has experience developing solutions that fit into the Industrial Internet of Things – from embedded control and monitoring (edge node solutions) to test asset monitoring & real-time web-based dashboards for process monitoring. Please contact us if you’d like to discuss your requirements.




Introduction to Malleable VIs in LabVIEW

In my first LabVIEW-related blog post, I wanted to talk about a new feature introduced in LabVIEW 2017 – Malleable VIs. I will give an introduction to Malleable VIs, discuss some of their benefits/limitations and show some examples of how Malleable VIs can improve code reuse. I’ll expand on this post with more examples in subsequent posts.

The Problem

Malleable VIs are designed to implement ‘generics’ in G, a feature which can be found in other languages (e.g. C#), allowing you to create functions where the data type is not defined in the function and is determined either at compile or run-time. The use of generics allows you to improve code reuse since you can write a function once for many data types. If you find yourself writing (or copying+pasting) very similar VIs where only the data type on the connector pane is different, you probably want to have a look at Malleable VIs.

Before Malleable VIs, this was done in one of two ways:

Method 1 – Polymorphic VIs

The first method of supporting multiple data types is to use a Polymorphic VI, but I consider it to be cheating – essentially creating a separate VI for each data type you need to support. This leads to large numbers of VIs that have to be maintained, most of which are essentially the same but with different data types on the terminals to avoid coercion.

As an example, here is the OpenG Sort Array function. This is a polymorphic VI that sorts a 1D or 2D array of most LabVIEW datatypes (e.g. numeric types, strings, paths). This leads to 33 different VIs – the polymorphic VI itself and the ~32 VIs that support the different data types.

OpenG Sort Array Function

Of course, if you wanted to sort an array of a datatype not supported by the OpenG Sort Array function, such as clusters, enums etc. then you would need to create an additional Sort Array VI for your data type to do so.

Method 2 – Variant Polymorphism

If you look at the functions of the OpenG/MGI toolkits, there are many VIs which take in and pass out a variant. Since a variant is a generic data type (it can hold any type of data at run-time), LabVIEW will automatically coerce any data type to a variant at the connector pane terminal boundary. This allows you to wire anything into a variant terminal, perform some operation on the data and then return the variant out. Inside the VI, however, you must handle the different data types (e.g. by type-casting) and it also requires the user of your VI to type-cast the variant back to the initial data type.

Below is an example of how this method is currently employed in the OpenG Read INI Section VI. The VI has a variant in (to define the expected data type/default values) and returns a variant which then has to be converted back to the original type.

OpenG Read INI Section VI – Variant Polymorphism

The Solution – Malleable VIs (.vim)

Introduced in LabVIEW 2017 was the new VI extension ‘.vim’ for Malleable VIs. With VIMs, the data types on the connector pane can adapt to any valid input (i.e. any data type where the VI can still compile / no broken run arrows).

In the following sections, I’ll show a basic and an intermediate example of Malleable VIs which should help to explain the concept.

Basics – Stall Data Flow.vim

I think most LabVIEW developers have at some point found themselves creating a VI like ‘Delay with Error Wires’ or ‘Tick Count with Error Wires’ for adding delays or benchmarking their code. Even if you haven’t, you’ve probably found yourself putting a sequence structure frame with a Delay primitive inside it and a wire going through. One of the Malleable VIs included in LabVIEW 2017 is Stall Data Flow.vim which replaces the ‘Delay with Error Wires’ with a VIM that can delay data flow on any wire type – making my VI ‘delay with error wires’ VI redundant (good!).

Stall Data Flow.vim – Examples

The content of the VIM is very simple – exactly the same as what’s in my ‘delay with error wires’ VI shown above but if you look at the examples at the bottom, any data type passed in is passed out without coercion dots – so you can use it with any data type. That’s the basic principle of the Malleable VI.

Intermediate – The Type Selector – Increment Array Element(s).vim

The next aspect of VIMs I want to introduce is the Type Selector. The type selector is a new structure specifically for VIMs that isn’t currently available on the palettes (as of LV2017 SP1 – probably coming in LV2018). It allows you to handle cases for specific input data types. The simplest example of which is to allow for a terminal to be a scalar as well as an array – as is the case in Increment Array Element.vim.

Increment Array Element VIM – Type Selector Structure

LabVIEW checks each case of the type selector until it reaches the first one that is valid (i.e. compiles), and it uses that as the implementation for the case. If a scalar is passed in, the VIM increments just the specified index and if an array of indexes is passed in, each element is incremented in a for loop.

To take it slightly further, there is also a ‘match type’ node which breaks the type selector case if the data types do not match, giving you another tool for handling specific cases in your VIM, but I won’t go into those here.

Advanced – Coming Soon!

There are also more advanced uses for VIMs (to do with using Malleable VIs as OOP interfaces, and some examples with sorting of arrays using custom sort functions) but I won’t go into those in detail as this is just an introduction. Stephen Loftus-Mercer from NI (AristosQueue) gave an excellent presentation at the CLA Summit in Madrid in which he showed many examples of Malleable VIs. There are some examples included in LV2017 SP1 and some more that should be shipping with LabVIEW 2018.

  • examples\Malleable VIs\Basics\Malleable VIs Basics.lvproj
  • examples\Malleable VIs\Class Adaptation\Malleable VIs – Class Adaptation.lvproj

If you have access to the CLA Community, he has posted a further example here.

My Example – INI Configuration API

One of the immediate use cases for Malleable VIs that jumped out at me was for creating a re-use library for handling INI configuration files. In many of my projects I use INI configuration files when I need a simple human-readable configuration file format. I use the OpenG configuration file functions, but I wrap them into a ‘Load Configuration’ and ‘Save Configuration’ VI with a type definition that contains the contents of the file. Here is what it usually looks like:

Load INI Configuration – Type Definition

This VI loads the INI file and if it (or some keys) can’t be found, uses the default values specified. It then writes the settings back to the file (which is useful to create the file on initialisation of the software). I create a ‘project-specific’ version of this VI (i.e. with a different cluster type definition) since I want to keep my top level block diagram (where I load the settings) simple.

Now, with Malleable VIs I have created the following:

Load Settings – Reusable VIM

I now have a reusable API for loading/saving INI configuration files (with the initialisation code), I can easily see the path/default values on the calling VI but I don’t have to convert the variant back to my settings type on the calling VI (and no coercion dots!).


Malleable VIs currently have one major limitation – they must be set to ‘inline’ in the execution properties. While this might not seem like a big deal at first (e.g. you have to disable debugging, no automatic error handling and must be shared/preallocated reentrant), this is actually more of a limitation than you might think – some LabVIEW nodes cannot be used in inlined VIs. According to the LabVIEW documentation, inline VIs cannot contain ‘certain’ block diagram nodes – the help mentions Property Nodes and Invoke Nodes (but there are others – I couldn’t find a list!). There is a flat restriction that inlined VIs cannot contain property nodes or invoke nodes (this includes class property nodes, even though the accessor VIs can be inlined). This unfortunately rules out many potential use cases for them – for example for UI manipulation.

Below is an example of something I thought would be a great candidate for a Malleable VI – something which sets VI properties on a bunch of control references. This Malleable VI would allow me to wire in either a scalar or array of control/indicator references and set some property (e.g. visible, disabled etc.) on all of them at once.

Set Disabled Malleable VI – Not possible due to inlining restriction

There is a LabVIEW Ideas exchange post about the issue, but with the inlining restriction of Malleable VIs I think it is more relevant now than ever so please go ahead and +1 it.


I think Malleable VIs are a really neat feature included in LabVIEW 2017 and I hope that this post goes some way in helping you to understand them and unlock their potential in your LabVIEW programming. It was a bit of a shame to discover I can’t use them to replace some of my UI utility functions, but I see that there are still plenty of other uses for them.

I’m very interested to hear/see how others are using Malleable VIs in their code – so if you have any examples/ideas then it would be great to hear them – please leave a comment below!