Jump to content

Missing external function errors in executable on hosts with a runtime engine


Recommended Posts

Hello, I wrote a LabVIEW program to communicate with a hardware sensor using vendor-provided LLB and a DLL files. The program runs fine on my workstation both from LabVIEW IDE and from a compiled executable. The problem starts when I copy the entire executable folder to a target host without a LabVIEW IDE (only with a runtime engine). The application opens with a broken Run arrow and a "missing external function" error message appears for every function call I made to the DLL (see attached).

I have tested my application on 5 completely different Windows 10 computers managed by different people. On three of them with various versions of LabVIEW IDE my executable opened with a whole Run arrow and no error message. Two other machines previously had no LabVIEW, so I installed a Runtime Engine 2017f2 32-bit with default settings to match the version of my IDE. Both gave an identical error message.

The DLL is always included in the application build. I have tried placing the DLL in every conceivable location on the target host: in the executable folder, in the /data folder, in the c:\Windows and system32 folders... I even created a full folder tree matching the location of the project on the developer workstation. Same error. When I intentionally hide the DLL, my executable prompts me to point to it upon being opened, and when I do, I get all the same error messages.

Vendor documentation only asks to put the two files in the same folder. From programmer's manual: " The driver was written in LabWindows/CVI, version 4.0.1 and is contained in a dynamic link library which can be linked with a variety of programming languages." There is no vendor-provided support.

One way I actually got rid of the error message was by editing every Call Library Function Node in every VI in the LLB to use relative path to DLL together with the Application Directory VI. However, I feel that there has got to be a better way to compile than by editing a vendor-provided library, especially since it works as-is on some computers. Can anyone suggest what it is?

Thank you for your time!

 

failed_application.png

Edited by Billy_G
Link to comment

Obviously your DLL has other DLL dependencies. And it is the task of Windows to resolve such scondary dependencies. But Windows won't search in the directory the referencing DLL is. Instead Windows has a number of standard locations it will look for such DLLs. Make them appear in one of those directories and things are well.

1) if already loaded it will simply reuse the DLL

2) In the directory the process exe file resides

3) in the Windows\System32 directory

4) in the Windows directory

5) in the current path, which starts in the process exe directory but is affected whenever you dismiss the file dialog in an application

6) in one of the directories listed in the PATH environment variables.

The quick fix is to move your DLLs in the same directory as your build exe

You most likely have installed the driver at some point on your machine and it put copies of the DLLs in Windows\System32. You then copied those DLLs into your project library but all but the directly called DLLs through the Call Library Node are then basically never used since Windows will find and load the DLLs from the system directory.

Edited by Rolf Kalbermatter
Link to comment

As I have said in my original post, I tried placing the DLL in most of the locations you enumerated, including a directory tree perfectly matched to the project location, with no luck. All the vendor gave me were one LLB and one DLL in a zip file. I just unpacked and added them to the LabVIEW project. There was no driver installation, no subsequent copying of some DLLs but not others. And the fact that the error messages are about missing functions in that DLL makes me think that it is not related to other DLL dependencies.

I emailed a zipped up executable to a colleague with a LabVIEW IDE, and I have no idea where he unzipped the files or what his version of LabVIEW was, but he said it loaded without an error message on the first try.

Edited by Billy_G
Link to comment
1 hour ago, Billy_G said:

As I have said in my original post, I tried placing the DLL in most of the locations you enumerated, including a directory tree perfectly matched to the project location, with no luck. All the vendor gave me were one LLB and one DLL in a zip file. I just unpacked and added them to the LabVIEW project. There was no driver installation, no subsequent copying of some DLLs but not others. And the fact that the error messages are about missing functions in that DLL makes me think that it is not related to other DLL dependencies.

I emailed a zipped up executable to a colleague with a LabVIEW IDE, and I have no idea where he unzipped the files or what his version of LabVIEW was, but he said it loaded without an error message on the first try.

Have you tried any kind of dependency checker? This can be useful in tracking down why a DLL is not getting loaded with LabVIEW.

https://github.com/lucasg/Dependencies

Now, I have come across one super weird issue last year which totally surprised me. I don't think this is the same thing you are experiencing, but see this thread for an explanation https://forums.ni.com/t5/LabVIEW/error-loading-lvanlys-dll-in-Labview-64-bits/td-p/4009772

 

Link to comment
4 hours ago, Billy_G said:

As I have said in my original post, I tried placing the DLL in most of the locations you enumerated, including a directory tree perfectly matched to the project location, with no luck. All the vendor gave me were one LLB and one DLL in a zip file. I just unpacked and added them to the LabVIEW project. There was no driver installation, no subsequent copying of some DLLs but not others. And the fact that the error messages are about missing functions in that DLL makes me think that it is not related to other DLL dependencies.

I emailed a zipped up executable to a colleague with a LabVIEW IDE, and I have no idea where he unzipped the files or what his version of LabVIEW was, but he said it loaded without an error message on the first try.

If the driver itself only consists of this single DLL, then that still does not exclude the possibility of dependencies, but a little different than what I deduced from your first post.

Every C(++) compiler will use a C (and in case of C++ also a C++) runtime library for all the standard functions that a programmer expects to be able to use. This runtime library is similar to the LabVIEW runtime engine.

While it is possible to include the relevant C runtime functions together into the DLL, this is often (and in Visual C by default) not done to make the DLL not contain redundant code that is elsewhere available on the system. Now most C compilers have long ago started to use version specific C runtimes. If your DLL was created with Visual Studio 2010 for instance, it is set to depend on the Micosoft C runtime  version 10.0. A Visual Studio 2012 executable or DLL is dependent on Microsoft C runtime version 11.0.

Each C runtime has its own set of DLLs that need to be present on the target system in order to load a DLL or EXE created in the according Visual Studio version.

Microsoft Windows comes pre-installed with some C runtime installations and that can vary over time since various Windows tools are compiled with various Microsoft C compiler versions. And LabVIEW and many of the NI tools are created in various versions of Visual Studio too. So what most probably happens is that on a full LabVIEW IDE install some of the libraries or tools installed uses the exact same runtime version as your DLL. On a normal LabVIEW runtime installed machine this specific NI tool or library is not necessary and hence not installed and therefore loading of your DLL must fail.

Your DLL manufacturer needs to document in which version of Visual Studio the DLL was created to let you download the according Microsoft C runtime installer from the Microsoft side (or provide that installer together with their DLL).

Edited by Rolf Kalbermatter
Link to comment
2 hours ago, Neil Pate said:

Now, I have come across one super weird issue last year which totally surprised me. I don't think this is the same thing you are experiencing, but see this thread for an explanation https://forums.ni.com/t5/LabVIEW/error-loading-lvanlys-dll-in-Labview-64-bits/td-p/4009772

It's not really weird. The NI Analysis library is only a thin wrapper around the Intel Math Kernel library. And that library does all kinds of very low level performance enhancing tricks. Part of that is that it determines at loading what CPU, number of cores and which SIMM extensions the CPU supports to tune its internal functions to take maximum advantage of the CPU features for performance reason.

It so happens that the detection code for this trips over its feet when presented with an AMD Ryzen CPU and rather than falling back to a safe but not that performant option it simply aborts the DLL loading which in turn aborts the LabVIEW wrapper DLL loading. LabVIEW doesn't know why the loading of the DLL failed, just that it did fail.

Of course, anyone suspecting any malevolence in that failure of detecting a competitors CPU, really must be ill minded. 😀

Realistically I suspect it wasn't malevolence, but the fact that it wasn't for their own CPUs didn't quite make the urgency to fix it very high. And NI doesn't update the AA library every few months to the latest and greatest MKL release, as that has some serious implications in terms of testing effort. 

Edited by Rolf Kalbermatter
Link to comment
21 minutes ago, Rolf Kalbermatter said:

It so happens that the detection code for this trips over its feet when presented with an AMD Ryzen CPU and rather than falling back to a safe but not that performant option it simply aborts the DLL loading which in turn aborts the LabVIEW wrapper DLL loading.

As I said, weird... 🙄

Link to comment
2 hours ago, dadreamer said:

Might it be that LabWindows/CVI RTE should also be installed on a clean machine? DLL dependencies utility shows, that QCMM2000.DLL depends on cvirte.dll. I'm not sure, where you could download 4.0.1 RTE for LabWindows, it's not available on NI.com. Maybe try to request it from the vendor?..

2020-12-03_18-03-11.jpg

Yes it could if this driver was developed in LabWindows/CVI. And there are some parts that get installed with LabVIEW that were in fact developed in LabWindows/CVI and therefore will cause the runtime engine to be installed. LabVIEW runtime itself does not need it however so its logical that it does not install them.

Where did you deduce that it needs the 4.0.1 version of the CVI runtime?  That is an awfully old version released about 25 years ago. I would guess that the DLL needs a newer version unless it was released in the late 90ies of last century.

Edit: I just see that the copyright is 1997 to 2001 so your version might be in fact not very much off. Although a never LabWindows/CVI should work too. LabWindows/CVI did not use version specific runtime libraries and the functions were usually kept backwards compatible.

Edited by Rolf Kalbermatter
Link to comment
44 minutes ago, Rolf Kalbermatter said:

Where did you deduce that it needs the 4.0.1 version of the CVI runtime?

It's in the OP's first message.

On 12/2/2020 at 12:54 PM, Billy_G said:

From programmer's manual: " The driver was written in LabWindows/CVI, version 4.0.1 and is contained in a dynamic link library which can be linked with a variety of programming languages."

 

45 minutes ago, Rolf Kalbermatter said:

Although a never LabWindows/CVI should work too.

Then it's worth trying RTE 5.5 at least.

  • Like 1
Link to comment
  • 3 months later...

Thank you, dadreamer! There is, in fact, a dependency on cvirte.dll, which is installed on my development host, but not on the deployment host. I tried installing RTE 5.5, but it would not run on Windows 10, no matter what compatibility settings I pick (I tried all options back to Win 95). So, instead, I matched the version of the cvirte on the development machine (19.0. ...), not of the vendor's code, and voila!

Link to comment
  • 7 months later...
On 3/18/2021 at 9:24 AM, Billy_G said:

Thank you, dadreamer! There is, in fact, a dependency on cvirte.dll, which is installed on my development host, but not on the deployment host. I tried installing RTE 5.5, but it would not run on Windows 10, no matter what compatibility settings I pick (I tried all options back to Win 95). So, instead, I matched the version of the cvirte on the development machine (19.0. ...), not of the vendor's code, and voila!

As mentioned, the cvirte.dll is not version specific. The CVI developers apparently tried to avoid that version incompatibility shenigan. So a newer CVI runtime engine install should work. There is a small chance of a version compatibility bug in a much never version, but as long as it works, it works. 😀

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Similar Content

    • By torekp
      DLL functions or shared variables?  Or something else?
      I have a Labview 2014-64 executable (or I can build a DLL) that runs one piece of equipment, the X-ray.  The other engineer has a large CVI Labwindows 2015 + MS Visual Studio 2012 (C++) executable that runs everything else.  I want the Labview code to be a slave of the CVI code, accepting commands to turn X-ray On or Off, reporting failures, and the like.  Translating the X-ray code into C++ would be possible in principle, but not fun.
      Shared variables look easy, but I'm kinda scared of them.  I would define all the shared variables in my LV code, since I'm more familiar with LV, then use them in both.  There's a thread in here called "Shared Variable Woes" so maybe I should be scared.  In the alternative, I tried building a proof-of-concept DLL in Labview, and calling its functions in CVI/C++, and it works, but it's kinda clunky.  (I'm attaching it below in case you want to play, or advise.)
      Your advice would be appreciated.
      XrayDLL.zip
    • By Dawid
      I'm trying to execute LPR.exe command to print some labels on a printer. However as its normal, problems occur. I could not find answer on any topic conneced with "sytem exec". I already tried all described methods (I think so). That's why I'm asking very kindly for any help.
      When trying to execute or call the LPR.exe from System exec VI, I'm receiving error:
      "'C:\Windows\System32\lpr.exe' is not recognized as an internal or external command, operable program or batch file."
      Generally I would like to call function: "lpr -S 192.168.1.5 -P lp C:\test\do_druku.txt" which works from command window without any problem.
       

      print.vi

    • By patufet_99
      To use a controller from LabVIEW I have to use some functions of a DLL.
      For one of the functions, according to the header file .h there is a structure data with parameters of different types that I have to pass to the dll. Some of the parameres are BYTE (1 Byte)  and WORD (2 Bytes).
      When compiling this kind of structure with Visual C++ and looking at it's size with "sizeof()" it seems to me that 4 Bytes variables have to start in a position multiple of 4. For example if there is a BYTE and then a DWORD, the 3 Bytes after the BYTE are ignored and the DWORD starts at Bytes 5 to 8.
      When defining a LabVIEW cluster to match the DLL structure, will LabVIEW do the same? If in my cluster there is a U8 variable and then a U32, will anyway the U8 take 4 bytes?
       
      Thank you.
    • By torekp
      So I created a DLL from a Labview VI that has a 2D array input (and some scalar inputs) and some 2D array outputs.  Labview creates a .h file with these lines

      And then it defines the 2D array arguments to my function as being of this type: "void __cdecl Linear_discrim_4dll(DoubleArray *dataObsFeat, int32_t grpAsz," etc etc.  Trouble is, I have no idea how to fill out this structure so that the DLL can use it.  Say for simplicity I had a 2 by 3 input called dataObsFeat with elements {1,2,3; 11,12,13}; how would I create the object with these values in C or C++ and pass it to the function?  I am a total C++ noob, in case it isn't obvious.
    • By ensegre
      I wonder if someone ran into this and has a good suggestion about. I have a DSC project, in which it looks just right to organize hierarchically my shared variables. Like, e.g.

      Now this is easy to do programmatically, see the attached project. The problem arises when building an application. It would look as if the plain way to do it, would be to create a build specification which includes the additional libraries, and select their deployment in the "Shared Variable Deployment" tab. However, this doesn't seem to work for nested libraries as in my example. The only possibility seems to add in "Always included" each of the contained libraries. But by doing like this the hierarchy is flattened.
      If I include like this,

      then the variables within the container library are not deployed at runtime.
      In my example project:
      open the project in the IDE, run DeployAllSharedVariables.vi, then CheckDeployed, and see the result (all four variables found with their nested paths) build and run DeployFlatLibraries and see the result: four variables, but flattened paths build and run DeployHierarchicalLibraries: only the two variables in the unnested SimpleVariableLibrary are there. I've searched a bit, and only came up with this document, which (for >2009) says "just check the checkbox". Nor the help page says much either.
      I wonder if I can do what I'd like only compiling separately the libraries, and loading them programmatically afterwards, both in the IDE and in the exe. Which probably is sane, but inconvenient for the first attempts.
      TestDeploy.zip
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.