LabWindows/CVI is in maintenance mode with a four-figure seat price. Here are the realistic replacements for ANSI C test applications, and how to migrate without rewriting a decade of code at once.

LabWindows/CVI is NI's ANSI C development environment for test and measurement applications, combining a C compiler, instrument driver libraries, a UI builder, and analysis functions. It is the text-based counterpart to LabVIEW, and it has been the backbone of production test applications in aerospace, defence, and semiconductor for decades.
It is also in maintenance mode, carries a four-figure per-seat subscription, and increasingly struggles to find engineers who want to work in it. This post covers the realistic alternatives and, more usefully, how to migrate an application that has been running since 2009 without stopping production.
It is not that the tool is bad. Written well, a CVI application is fast, deterministic, and has run unattended for years.
The problems are structural:
That last point is what makes migration feel impossible, and it is also why the migration strategy below matters more than the tool choice.
Open a typical one and the line count breaks down roughly like this:
| Layer | Share of code | Migration difficulty |
|---|---|---|
| Instrument communication (VISA calls, SCPI strings, error handling) | 30 to 40 percent | Easy, mechanical |
| Test sequencing (what runs in what order, retries, limits) | 25 to 35 percent | Easy, mechanical |
| UI panels and callbacks | 15 to 25 percent | Moderate |
| Measurement algorithms and maths | 5 to 15 percent | Hard, and worth preserving |
| Report and file output | 5 to 10 percent | Easy |
The two largest layers are the two easiest to replace. That is the insight that makes migration tractable. The part that is genuinely hard, your calibration maths and your domain-specific algorithms, is a small minority of the code and can usually be kept as-is.
Free, and the destination most teams end up at.
import pyvisa
rm = pyvisa.ResourceManager()
psu = rm.open_resource("TCPIP0::192.168.1.42::inst0::INSTR")
dmm = rm.open_resource("USB0::0x2A8D::0x1301::MY57200001::INSTR")
psu.write("VOLT 3.3"); psu.write("OUTP ON")
dmm.write("CONF:VOLT:DC 10,0.0001")
vout = float(dmm.query("READ?"))
psu.write("OUTP OFF")
assert 3.2 <= vout <= 3.4, f"VOUT {vout} out of limits"Good for: the instrument and sequencing layers, which is most of the application. Hiring is easy, the ecosystem is enormous, and it runs in CI.
Gives up: hard determinism and the UI builder. Python on Windows is not a real-time environment, though for the vast majority of CVI applications it was never actually relying on that.
Keeping your C: compile your measurement algorithms as a DLL and call them with ctypes. Validated maths stays validated.
Verdict: the default recommendation. See the PyVISA tutorial.
Generates the instrument and sequencing layers rather than having you rewrite them. You describe the test in plain English, name the instruments, and it produces the automation and runs it, with the report as an output rather than a thing you code.
Good for: exactly the 60 to 75 percent of a CVI application that is mechanical. It does not care that the original was C.
Gives up: the custom algorithms, which stay yours, and any hard-determinism requirement.
Verdict: the fastest route through the tedious majority of the migration.
Free VISA layer, your own compiler and IDE. Visual Studio, CMake, and a modern toolchain instead of the CVI IDE.
Good for: teams with real determinism requirements, teams with a lot of C they refuse to leave, and regulated environments where a language change triggers requalification.
Gives up: the UI builder and the analysis library, both of which you now source elsewhere. Qt or Dear ImGui for the UI.
Verdict: the conservative move. Keeps the language, drops the vendor lock. Often the right first step.
If the UI panels are what keeps you on CVI, Qt is the serious answer. Commercial and open-source licensing, C++ native, and cross-platform.
Good for: operator interfaces that need to look and behave properly on modern displays.
Gives up: nothing technical, but Qt has a learning curve and a licensing decision to make.
Verdict: pair it with Qt below for a complete non-NI C stack.
Free and open source sequencer from the Keysight ecosystem. Replaces the sequencing layer specifically, with plugins for instruments and results listeners for output.
Good for: the 25 to 35 percent of your code that is sequencing, with a supported structure rather than hand-rolled state machines.
Gives up: the UI and the C. Plugins are C# first.
Verdict: strong if you are also re-evaluating TestStand, since they compete directly.
| LabWindows/CVI | Python | C + VISA | Qt | OpenTAP | TestFlow | |
|---|---|---|---|---|---|---|
| Cost | Four figures/seat/yr | Free | Free | Free or commercial | Free | Free version, then paid |
| Language | ANSI C | Python | C/C++ | C++ | C# | Plain English |
| Instrument libraries | Extensive | pyVISA | VISA | None | Plugins | Built in |
| UI builder | Yes | No | No | Yes | Partial | Browser workspace |
| Determinism | Good | Poor | Good | Good | Moderate | Not real-time |
| Hiring pool | Shrinking | Very large | Large | Large | Small | N/A |
| Runs in CI | Awkward | Yes | Yes | Yes | Yes | Yes |
| Keeps existing C | Native | Via ctypes | Native | Native | Via interop | Alongside |
Do not rewrite the application. Strangle it.
Freeze the old application. No new features in CVI from today. Bug fixes only. This alone stops the problem growing.
Extract the algorithms first. Identify the measurement maths that is genuinely yours, pull it into a standalone DLL with a clean C interface, and unit-test it against known inputs. Do this while the old app still runs, and have the old app call the new DLL. Now the valuable part is portable and proven.
Build the new path for one test. Pick the single simplest test in the sequence. Implement it in the new tool, calling the same DLL. Run both, same DUT, same day.
Compare outputs numerically, not visually. Export both to CSV and diff them. Agreement to the measurement's own resolution is the pass criterion.
Move tests in batches, keeping the old app as the reference until the last batch. Production keeps running on CVI throughout.
Retire the licence at renewal, not before. You want the old app available until the new one has produced a full quarter of clean results.
The failure mode to avoid is the big-bang rewrite. Every CVI migration that goes badly is one where the team tried to reproduce the entire application in one go, discovered an undocumented behaviour in month four, and had no reference to check against because the old machine had been repurposed.
The single most useful technique. Your measurement algorithms are the part worth keeping, and they are already C.
In CVI, export the function:
__declspec(dllexport) double CalculateOffsetCorrection(
double raw_reading, double temperature_c, double cal_slope)
{
return (raw_reading - (temperature_c * cal_slope)) * CAL_FACTOR;
}Build as a DLL rather than an executable. This is a project setting change, not a code change.
From Python:
import ctypes
lib = ctypes.CDLL("./calibration.dll")
lib.CalculateOffsetCorrection.argtypes = [ctypes.c_double] * 3
lib.CalculateOffsetCorrection.restype = ctypes.c_double
corrected = lib.CalculateOffsetCorrection(raw, temp_c, slope)Two consequences worth being explicit about. First, the validated maths stays byte-identical, so no requalification argument applies to it. Second, you can now unit-test it from Python against known inputs, which is very often the first time that code has ever had tests.
Do this before touching anything else. It converts the scary part of the migration into a solved problem and makes every later step lower risk.
Sort the panels into three buckets and handle each differently.
The realistic outcome is that a 25-panel application needs two panels in the new stack.
The other thing CVI gave you was a large library of instrument drivers, and losing them feels like losing capability. In practice most of those drivers are thin wrappers over SCPI strings you can send directly.
A CVI driver call like this:
Agilent34401_ConfigureMeasurement(handle, AGILENT34401_VAL_DC_VOLTS, 10.0, 0.0001);
Agilent34401_Read(handle, 10000, &reading);Is this over pyVISA:
dmm.write("CONF:VOLT:DC 10,0.0001")
reading = float(dmm.query("READ?"))The driver was saving you a lookup in the programming manual, not solving a hard problem. For the handful of genuinely complex instruments (a VNA calibration sequence, a spectrum analyser sweep setup) the vendor usually ships a Python package now, and where they do not, the SCPI command cheat sheet covers the common classes.
Two cases where the CVI driver is doing real work and deserves care: instruments with binary block transfers (waveform captures, trace data), and instruments with awkward status-byte handshaking. Both are solvable, both take an afternoon each, and both should be on the migration inventory rather than discovered late.
Three different things get called "keeping the C", and they have very different costs.
| Meaning | Effort | When it makes sense |
|---|---|---|
| Keep the measurement maths as a DLL | Days | Almost always. Do this first |
| Keep the C application, drive it from outside | Weeks | When the app is a black box that works |
| Rewrite the C in C++ with Qt | Months | Only if determinism plus a rich UI are both required |
The first row is the one that de-risks everything else, which is why it is step 2 in the migration above and not step 5.
Worth being straight about, because the decision goes wrong in both directions.
The case for leaving is not that CVI is bad. It is that the hiring pool is shrinking, the licence stacks on top of the rest of the NI bill, and the application is usually one retirement away from being unmaintainable.
The reason CVI code survives so long is that rewriting the instrument sequencing is tedious rather than difficult. That is precisely the part an agent can generate.
Connect your instruments. Pick the manufacturer and model, paste the VISA address (USB, LAN, GPIB, or serial), and the agent knows what is on your bench. No bench yet? Use a placeholder address, build the full automation, and swap in the real address when you are in the lab.
Tell the agent what to test, in plain English. For example, "run a VI sweep from 1 to 10 V in 1 V steps at 0.5 A load current," or "suggest the tests for a power-management device."
The agent builds the complete workflow in seconds. Instrument-aware automation appears on the canvas, with the generated scripts visible in a code panel you can inspect and edit.
Run it in your lab. Click Run and the status panel streams results step by step, with measured values inline (VOUT = 3.301 V, asserted 3.2 to 3.4 V, PASS). One click exports a structured PDF report, or the raw results as CSV.


The step-by-step walkthrough, VISA address formats, and Test Planner prompts are all in the TestFlow product guide.
It is not deleted, but it is in maintenance mode. NI has moved active investment elsewhere, releases are infrequent, and new hardware and OS support arrive slowly. Treat it as legacy for new development.
It is sold per seat on subscription, typically low-to-mid four figures per seat per year, with runtime and deployment considerations on top. Pricing is quote-based and region-dependent.
LabWindows/CVI is an ANSI C development environment with instrument libraries and a UI builder. LabVIEW is graphical dataflow programming. Both are NI products for test applications, but CVI suits teams who want text-based C.
Yes, if you compile it as a DLL. Python's ctypes or cffi can call exported C functions directly, which lets you keep validated algorithms and replace only the application shell and instrument layer.
Yes. Plain C with NI-VISA or Keysight IO Libraries is free for instrument control, Python with pyVISA is free, and TestFlow has a free version. The UI builder is the piece with no direct free equivalent.
Usually not all of it. The instrument communication and sequencing layers are the easiest to replace and the largest by line count. Custom measurement algorithms can often stay as compiled C called from the new layer.
Connect your instruments, describe a test in plain English, and TestFlow builds and runs it in minutes.
A new way for testing, from specs to automated sequences, capture clean data, and accelerate your validation cycle.