03-01-2024 02:52 AM
Hi,
I my instrument SW framework I integrated some Thorlabs stages with BSC0x motion controller. I used the Kinesis .NET library to make the low level APIs.
The VI "Connect.vi" holds the .NET constructor from where I start the communication with the motion controller.
The 1st problem is that I always have to open the low level project first and then open the "Connect.vi" otherwise the .NET constructor cannot find the .NET dll. Question: is that normal? In "Option/paths" I added the path where to search the dll, but nothing has changed. I always have to open the low level project first and then the vi.
But so far not big issues, but there are abstraction layers. On top of the APIs I made a "child" class, and it works as long as I open the low level project.
The issue comes when i call the parent class and make an instance of the child. In this case, even with the low level project open, the .NET constructor does not find the .NET dll and return an error. If I stop the VI and try to browse the dll manually, I get the error in the picture. The assembly mentioned in the error is in the same folder as all the other dlls.
Is there a right way to import these .NET dll and make them visible at different levels? The drivers should be then called by TestStand and I do see issue there as well.
Thanks in advance for your help.
03-01-2024 05:31 AM
Hi,
I found a workaround to make at least the parent class work, which is open the project and the "Connect.vi" at the very beginning and let them open. Very bad but at least work.
When the parent class create an instance, it is an instance of the "Connect.vi" I had opened.
When I do the same in TestStand, it creates another instance of the "Connect.vi" which does not find the .NET dll.
I then added a direct call from TestStand to the "Connect.vi" skipping the classes, and it works since it calls the "Connect.vi" I had opened. But then in the step after I call the class that open another instance and of course it does not work. (picture attached of the double instance of the same vi)
Is there any way to force to use the same instance of VI and not open multiple?
Thanks.
03-01-2024 10:18 AM - edited 03-01-2024 10:19 AM
I ran into a similar problem when creating a hardware abstraction layer for a bunch of different positioner device families (Newport, PI, Thorlabs).
When I tried to create an instance of an object using a Thorlabs device, it failed.
I think the problem with the Thorlabs Kinesis .Net VIs is that they communicate with the object on the front panel. The front panel updates when settings are changed programmatically and you can even operate the devices from the front panel object. I think this requires that the front panel be open (not sure).
My solution was to create a .Net constructor on the block diagram and avoid the front panel .Net container altogether.
The main challenge was to drill down deep enough in the .Net assemblies to find the required reference for the constructor for a particular device family. I think the code also required use of slightly different functions within the Kinesis .Net assemblies than those used with the front panel object. Once I got this going I could create multiple devices without needing the front panel containers.
03-01-2024 11:44 AM
I had the problem with that exact same DLL error.
I solved it by adding a constructor for a random object from the offending DLL to my VI, then immediately closing it:
Doing that put the DLL in memory as soon as the VI starts loading so that it can use LabVIEW's direct saved path to the DLL instead of trying to rely on the DLL finding its own dependencies, which is unreliable.
03-06-2024 05:34 AM
Thanks John and Kyle,
You’re both right, then I followed your recommendation to replace the GUI .NET constructor with one on the block diagram. Still pretty unstable and it work only is specific condition that I did not fully understand. But I found a configuration that systematically work loading the project in advance. Then to avoid the pre-loading I did it programmatically and it works.
It works in the following conditions:
Then I also try to call directly the child class of the BSC, skipping the parent, but still the same error.
I am running out of ideas.
03-06-2024 11:07 AM
I've used Kinesis stuff in the past and had similar issues. After communicating with Thorlabs the said the solution was to copy all of their DLLs to the same folder as the lvproj file and in the same folder as the Exe when deployed. I haven't had any problems since.
03-06-2024 12:29 PM
I will admit that I have never tried calling a Kinesis DLL from TestStand directly.
When calling a DLL, LabVIEW is not "in charge" of where a DLL looks for other DLLs it needs. Windows is. There are 3 places it looks:
1. Currently loaded in memory
2. In what it considers to be the "Base directory" of the application running (but not subdirectories of this directory!)
3. The Global Assembly Cache, "GAC", i.e. this is where all the system DLLs reside, as well as DLLs that get "properly" installed by an installer to now be a part of Windows.
Putting things in the GAC as a LabVIEW user is basically impossible now. In older versions of Windows with Admin logins you could add things, but security problems caused that to be closed. As convenient as this would be, don't try it.
The next option, the "Base directory", is problematic with LabVIEW applications. This is because it changes based on what you're doing:
TestStand probably has its own rules for this.
To check what this base directory is, you need to run a .NET call. In the "mscorlib" assembly, find the "System" namespace, then choose the AppDomain class, then read the static "CurrentDomain" property, and from that object get the "BaseDirectory" property. This is what it looks like in LabVIEW:
You should be able to find and call it similarly from TestStand, and can try it under different situations to see where it looks, i.e. if it loads from different places based on what LabVIEW or the Runtime is doing depending on your setup.
The last option, "Currently in memory" was what I was doing earlier. When I posted this:
The important part is that it forced LabVIEW to load "Thorlabs.MotionControl.Tools.WPF.UI.dll" into memory when it loaded the VI containing it, so that when the other DLL call tried to use it, it was already in memory and didn't need to try the other two options.
ThorLabs has about 100 DLLs in Kinesis, but if you can one by one find out which ones it's mad about missing and put in direct calls to them before calling the one that fails, it may be a way of making it work, though a kind of a janky one.
03-06-2024 01:34 PM
One other thing I recall - I noticed you had the benchtop stepper control UI on the front panel, which is what I had done initially. The problem with the Kinesis UI dlls is that they will sometimes pop up modal dialog box error messages. I had an issue with the dll putting up an error dialog "no suitable device found" when it couldn't find the motor. I was instructed to use the CLI classes instead. Hope that helps prevent future issues.