LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Loading .net dll failes

Solved!
Go to solution

Hi there,

 

I am really new in LabView, but I tried to load our .net dll to call it from LabView.

 

Here comes the confusing part about it: When I create a completely new project with a new VI and try to load the dll over Connectivity --> .Net --> Constructor Node and select our Assembly an error message occurs "There was an error on loading the assembly". What really strikes me is, that it workes when i manage to have a dependency on the dll (was possible with a workaround). So it seems to me, that LV uses two different loading mechanism whether the dll have already been used or the dll is newly tried to be inserted.

 

Does anyone have an idea what happend here? My investigations showed that there has to be a problem on resolving embedded ressources used in our dll (but as said, it worked when the dll has already been in the dependencies).

 

I used LV Version 21.0.

 

Thanks in advance for any help.

0 Kudos
Message 1 of 8
(4,812 Views)

Is your .Net assembly a pure .Net assembly written in C# and compiled to platform independent IL code or a hybrid one with C++/CLI code?

Do you have any unmanaged binary dependencies in the .Net assembly called through platform Invoke or other marshalling mechanismes?

What do you mean with embedded resources? I suspect that you mean platform Invoke referenced external dependencies which is the total opposite to embedded! 

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 2 of 8
(4,800 Views)

Our assembly is a C++/Cli assembly, but that is not the problem though.

 

We have embedded resources in our main assembly. That means we internally put all our dependent assemblies together in just one output dll. It seems that LV then has a problem to resolve all the embedded dependencies in the main assembly (Sure that is not LV daily business).

 

But my biggest surprise was, that it worked when the same dll was in the dependencies of the LV project. Then, LabView was able to load it.

0 Kudos
Message 3 of 8
(4,784 Views)

That's not LabVIEW's fault. LabVIEW is NOT concerned (and should not even try to be) about loading dependencies of your main DLL. That is all done by the Windows module loader and that has very specific locations where it searches for such dependencies. And the current directory where the referencing DLL is located is specifically NOT part of this list of locations where the Windows loader will search in.

 

LabVIEW tries to load the main library that your VI references and nothing else, usually with the absolute path to the library. Everything after that is purely Windows loading mechanics and completely out of hands of LabVIEW.

 

And the locations the Windows loader will look for dependencies is as follows:

 

1) is the library already in memory? -> great, use it

2) is the library in the same directory as the executable file for the current process? -> load it

3) is the library in the <system32> (or SysWOW64 directory for 32-bit applications) => load it

4) is the library in the <windows> directory? -> load it

5) is the library in the <current directory> for the process -> load it

6) is the library in one of the directories listed in the PATH environment variable? -> load it

7) still not found? sorry I'm out of options and give up with an error return code

 

This is for binary DLLs which is what your C++/CLI code pretty much is.

 

Now if you somehow load the DLL dependencies through other means before letting LabVIEW try to load the main DLL, everything will of course work as Windows sees in step 1) that it is already loaded.

 

As an extra nastiness there is also step 5). Windows has the "strange" feature to update the <current directory> for a process whenever the system file dialog is dismissed in an affirmative way, by updating the current directory to the directory that the dialog is in at that moment. So this means when you go in LabVIEW to select the main DLL that it claimed to not be loadable since Windows denied it initially and your dependencies are in the same directory, it "magically" seems to work until the next time you start up the application.

 

And if your dependencies are all .Net assemblies too instead of classic DLLs, things get even more nasty. For those the .Net loader only considers the directory in which the current process executable is located and the Global Assembly Cache as valid locations to search for dependencies.

 

An application can create a non-default AppDomain which adds additional directories to search for .Net assemblies and LabVIEW actually does that to add the project directory as searchable path, but that's it. But it's a mechanism that got severely restricted in newer .Net versions and is highly discouraged in the documentation as being potentially unsupported in future .Net versions.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 4 of 8
(4,776 Views)

This sounds similar to a problem we have with a custom DLL at my company that also bundles a lot of dependencies in it.

 

The DLL in question is one we use for data saving, so that all programs (LabVIEW, .NET, others) can all call it as a common method for saving data to our company database.  Because it's companywide, any time a station needs a new feature, anything new it needs to save can sometimes result in a DLL update that we have to implement.

 

This all worked fine for a while, until about a year ago when a new feature was added where in addition to saving data it could be used to look up some data that already existed in the database first (to do a delta measurement).  This added some new code to the DLL, which added a new dependency.  And for some unknown reason, any new usage of the DLL couldn't be done any more in LabVIEW. 

 

Use of any already existing code still worked though. So I tried to figure out what was going on.  I never figured out what caused it, but I did figure out a workaround in my particular case that worked.  If, before trying to create a brand new .NET node (constructor or otherwise), if I went to a  location calling the DLL in some certain places (but not others) it would still load it correctly.  Then once it did that and after I ran the class browser with that existing node as a starting point, I could make new nodes as well.  My best guess as to finding "working" nodes is that they seem to belong to classes early in the alphabet (As and Bs), but that could just be a coincidence.  I haven't checked the entire library to see which old nodes work and which don't.

 

At any rate, the only thing I can think is that the dependency packing code in the DLL is somehow only partially working with LabVIEW, and there might be some sort of weird "bootstrapping" issue where a new .NET call tries to load things in one order and fails, but some other .NET calls that already exist loads things in a different order that works.

 

So, I don't know if that specifically helps since it's a lot of guessing, but...

Was there a version update to the DLL between the version in the project that does work compared to the version you want to use new?

If so, can you try the old version of the DLL to see if it works fine?

Do you have any older working .NET nodes that you could check to see if the same thing happens to you with?

 

0 Kudos
Message 5 of 8
(4,750 Views)

I have to admit that I have not a good idea as to what that embedded DLL resource business might be. One possible thing is that this uses a feature that is present in the default AppDomain that .Net will create when an application starts up without defining a custom AppDomain but since LabVIEW creates its own AppDomain to allow loading assemblies from the project directory in addition to the standard directories, this doesn't get automatically added to the explicitly created AppDomain.

 

If it is something like that it would be kind of a .Net error to not add that feature to the explicitly created AppDomain as default.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 6 of 8
(4,740 Views)
Solution
Accepted by topic author .NetDeveloper

Hi together,

 

What you told Kyle is almost the same problem we have. An older library of our DLL works, but the newer one does not. Furthermore, the behaviour is a little bit weird: When I have the new Api already as a dependency in our project (was possible when I saved the project with the old Api and then put the newer over it), there is no problem on loading it, but when I try to load the Api in a new project, there is an error message.

 

Therefore my guess is, that LabView has two different loading mechanism whether a DLL is loaded directly in the project or over a dependency with a fixed path.

 

I wrote the support, but seems they can not help me. I will close this issue because I am really sure, here only LabView can help me and tell what they do different on loading the DLL and I found the workaround as described upwards.

 

 

0 Kudos
Message 7 of 8
(4,710 Views)

Secondary dependencies are NOT loaded by LabVIEW, that is the task of the CLR. LabVIEW can't and shouldn't try to know about such dependencies and leaves that part blissfully to the CLR.

 

What LabVIEW does is to use AppDomain contexts when a VI that references a .Net assembly is loaded from a project. That AppDomain context changes the default search order to rather look in the project directory and subdirectories rather than in the executable directory (which is where the LabVIEW.exe resides when you run a VI in the IDE).

 

So if you run from a project, all .Net assemblies should either be in the GAC or inside the project directory or the .Net CLR will not be able to find them, if you run without a project, they need to be in the GAC or in de LabVIEW directory, but putting files into the LabVIEW directory is NOT a good idea.

 

For assemblies that are directly referenced by LabVIEW VIs through a refnum control or constructor referencing a class in them, it doesn't matter that much since LabVIEW knows the path of them and can load it anyhow with the full path but any dependencies of these assemblies need to be in the above mentioned locations or .Net will have trouble to find it.

 

My guess to the earlier problem is that the assembly is in fact more than just a simple assembly but more like a collection of assemblies. When a constructor node is connected to a class in one of the assemblies inside this collection, LabVIEW stores the path to that "assembly" and requests to load it with the full path from .Net. .Net then finds that it needs to load other dependencies and unless the combined assembly collection is in the .Net search path it can't find them, despite that it has opened that "assembly" already. But in reality it hasn't, since it only has opened an assembly inside that assembly collection.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 8 of 8
(4,704 Views)