LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Problems when instrument driver .NET DLLs call other .NET DLLs

At my company we use the following system for organizing VIs on a PC (all of which are running LabVIEW 2015, Windows 7):

 

Application code --> C:\LabVIEW Code\AppName\...

Common company libraries not related to instruments --> <user.lib>\LibName\...

LVOOP root class that all instrument drivers inherit from --> <instr.lib>\CompanyNameInstruments\

LVOOP child class implementing wrapper VIs for a certain instrument type --> <instr.lib>\CompanyNameInstruments\InstrumentType\

LVOOP child class implementing a specific instrument that overrides wrapper VIs--> <instr.lib>\CompanyNameInstruments\InstrumentType\SpecificInstrumentName

 

Every directory in user.lib, instr.lib, and "C:\LabVIEW Code\" has its own SVN repository.

 

This has worked OK for quite a while, with ~ 8 different instrument types and 1-3 specific instruments each.  Most used VISA interfaces.  We recently needed to add some motion control using ThorLabs Kinesis .NET DLLs, so I created <instr.lib>\CompanyNameInstruments\MotionController\ThorlabsKinesis\ and put in a ThorLabsKinesis.lvproj, a ThorLabsKinesis.lvclass, and so on.  I installed the Kinesis software and it installed 112 DLLs (plus 30 other files that appear to be required to use the DLLs since they have the same filenames exactly as some of the DLLS, but different extensions), all of which I copied to the folder and added to the class as per recommendation from their Kinesis LabVIEW guide.  

 

I then did my thing, creating wrapper VIs, and got a few assorted controllers and motors in which I proved I could control using "ThorLabsTester.vi" that I added to the project and the class. This part all worked fine, so I was done with the driver VIs and it was time to work on the code for the first station that needed to use the driver.

 

Here's where the problem started: The station code I wrote kept giving error 1172 (the most generic .NET error code possible for LabVIEW) with a message stating it was throwing System.IO.FileNotFoundException because it couldn't find a DLL.  

 

Experimentation showed that the driver VIs would work fine only under the following conditions: 

  • Running a VI in ThorLabsKinesis.lvproj with ThorLabsKinesis.lvproj's project window open

And the driver VIs would fail under the following conditions:

  • Running a standalone VI that calls ThorLabs VIs
  • Running a VI in a .lvproj in C:\LabVIEW Code\AppName\ (with that lvproj open or closed)
  • Running a VI in a .lvproj in C:\LabVIEW Code\AppName\ with ThorLabs.lvclass added to it with that lvproj open
  • Running a VI that's in ThorLabsKinesis.lvproj without actually having the .lvproj file open
  • Running a VI that's in ThorLabsKinesis.lvproj without actually having the .lvproj file open even if the VI is in the same directory as the ThorLabsKinesis.lvproj file

 

This led me to this knowledge base article about how LabVIEW finds .NET DLLs listing 3 methods for locating .NET DLLs.  

 

I was hoping that the "Relative path" option would work, but 1) there's 112 DLLs that would have to be added, which seems ridiculous since I only call about 15 of them directly and 2) a lot of those DLLs don't have public methods for me to create a constructor/property/invoke node for to get them in the VI in any case.  I can't find a way to force LabVIEW to be told "If a DLL gets loaded, here's a directory where it should look for its friends" or something to that effect.

 

The "Specified Subdirectories" include both the folder the project is in, and the folder where LabVIEW.exe is.  The plan is to use this driver on the one station for now, but we have future plans to roll out about 5 other stations that use the same driver but for different applications, and it's hard to say how many more in the future.  I really don't want to have the same DLLs copied to 3 different locations per PC that we'll have to ensure all receive updates at the same time, etc.

 

The "Global Assembly Cache (GAC)" option seems like it would be an idea solution if it was easy to do.  However, the ThorLabs installer doesn't register the DLLs to the GAC when it installs.  I've spent hours trying to figure out alternate ways to accomplish this.  All solutions I find seem to be in the following categories:

  • Use a utility that comes with Visual Studio (gacutil.exe) to install things into the GAC (I don't have Visual Studio, and it's impractical to buy it and install it on every PC to do this)
  • Create an installer with Visual Studio to register the DLLS (see above, still don't have Visual Studio)
  • Drag + drop the DLLs into C:\Windows\assembly in an Explorer window (feature removed as of .NET 4.0)
  • Use the System.EnterpriseServices.Internal.Publish.GacInstall() method in .NET to add the DLL (also removed in .NET 4.0, fails silently when tried)
  • Force-load them with System.Reflection.Assembly.LoadFile() (changes the error number and message to "permission denied", seems that this method is only usable for non-NET DLLs)

Is there something simple I have missed here?  Has anyone else had the same issues with .NET DLLs for instrument control before?  Is my only real option to copy ~142 files to 2 or 3 locations on every PC instead of leaving them in one central source-controlled directory in the "right" place for an instrument driver?

 

Thanks...

 

0 Kudos
Message 1 of 7
(5,388 Views)
There are two aspects to finding DLLs. First LabVIEW has to find them so it can link to them, but then the CLR needs to be able to find them so it can actually run them.

To meet that later requirement for DLLs not in the GAC, a DLL can be in exactly one of two places: the same directory as the project calling it, and a subdirectory to that location called "data".

In addition, putting all your reusable code directly in the user.lib and instr.lib directories is asking for trouble since they are in turn located in the LabVIEW installation directory and it is anybody's guess how long before Windows completely locks down installation directories. In addition, it really isn't necessary since you can point mnu files in those locations to any directory you want and LabVIEW won't know the difference.

Mike...

Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
0 Kudos
Message 2 of 7
(5,368 Views)

@mikeporter wrote:

 it is anybody's guess how long before Windows completely locks down installation directories. 

Mike...

Do you have a source for this or is it just a "feeling" you get as Windows 10 starts rolling out, etc.?

 

(I'm still looking for a better solution to this issue, but thanks for the reply)

0 Kudos
Message 3 of 7
(5,319 Views)
Microsoft has been telling people this for years, and each new release of Windows gets more and more restrictive.

Mike...

Certified Professional Instructor
Certified LabVIEW Architect
LabVIEW Champion

"... after all, He's not a tame lion..."

For help with grief and grieving.
0 Kudos
Message 4 of 7
(5,315 Views)

I've managed a slight improvement.  Still not great.

 

I can get LabVIEW to work with the DLLs without opening a project file first (which was one of the things I really didn't want to have as a requirement, since operators will be running these stations and shouldn't be expected to deal with having a project file open in addition to the main application).

 

In order to get it working without the project file open, I need to:

  • Have the top-level VI be located in the ....\ThorLabsKinesis folder
  • I have to double-click the main VI to launch LabVIEW.  Opening it via any other method won't work (such as opening it from the pinned taskbar location, the start menu, or opening a main VI from another location, closing it, and then using the menus to open the main VI that's having issues)
  • I have to have the following in the LabVIEW.config.exe file:
<configuration>
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <probing privatePath="C:\Program Files (x86)\National Instruments\LabVIEW 2015\instr.lib\CompanyInstruments\MotionController\ThorlabsKinesis"/>
      </assemblyBinding>
   </runtime>
</configuration>

So it's still not really where I want it to be but it's progress of sorts.

0 Kudos
Message 5 of 7
(5,302 Views)

Is building a stand-alone executable an option?  If so, I have been able to get it working if I do 2 things:

  1. I place a copy of the dll file and all required dependencies into the project directory (the LabVIEW Development environment will use this copy) and add them to the Project (create a virtual folder to keep it organised).
  2. In the Application Build specs, specify that these dll's be placed in the root Application folder, not the support folder "data". The built app will find and use this copy.

It does mean copying all those files, but at least the built app is insulated from version changes of the dll's.  Then you just run the built app.

Message 6 of 7
(5,259 Views)

Building an EXE is an "eventual" option.  We do that when we "freeze" a station's development, i.e. when we've tested it live for a long enough time that we no longer have any significant amount of bug reports or feature requests and barring changes in the product line itself the station code shouldn't need to be modified further.

 

I have verified what you say, though.  If I just add every DLL in all of the drivers that are used to the build, it does work.

 

One thing I did discover during the whole process is that it seems that the DLLs that I mentioned don't have public methods for me to create a constructor/property/invoke node are not in fact .NET DLLs, and are older-style DLLs that the .NET DLLs call, so it seems likely that the .NET calls are just wrappers for their old code.  They offer both ActiveX/COM and .NET control methods for their products, so it could be they share these DLLs.

 

It may be that we'll just have to copy these DLLs all over the place and just do our best to ensure the same versions are used on a station-by-station basis instead of having a shared directory for all projects in SVN.

0 Kudos
Message 7 of 7
(5,226 Views)