LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Adding a .NET library to a VI with the .NET Constructor Node function

Solved!
Go to solution

Short version: I successfully loaded a .NET library in LabVIEW but it doesn't work.  Details below..

 

I wrote a simple .NET class library in visual studio using the .NET Framework 4.6.2 and targeting the x86 platform.  The constructor for the library requires a reference to a .NET panel control and adds a .NET SplitContainer control to that panel.  I tested the library by adding it as a reference to a simple WinForms project in visual studio.  You can see the SplitContainer in the upper left hand corner of the panel on the WinForm below.

 

form1gray.png

 

Then I created a LabVIEW project with a .NET Container on the Front Panel.  I tried using the the "Insert .NET Control" right-click menu option of the .NET Container but the dialog always complained, "This assembly contains no public controls." even though I tried making the SplitContainer control accessible by encapsulation and by declaring it public. 

 

Eventually I added a .NET panel object  to the .NET container on the front panels and then from the block diagram tried using the .NET "Constructor Node" function from the .NET subpalette of the Connectivity pallet.  The .NET library loaded fine and the constructor argument and other public functions appeared as expected in the block diagram.

 

block diagram.png

 

The only problem is that the SplitContainer never appeared in the Pallet of the front panel after running the VI.

 

LabVIEW result.png

 

I tried calling the .NET Panel methods Show(), Refresh() and Invalidate() using the functions inside my library but the SplitContainer never appeared.  The .NET Constructor Node would not accept a reference to the panel or a local variable representing the panel.  It seems I'm very close but no cigar.   Any thoughts?

 

 

I'm using LabVIEW 2019 32-bit which uses the .NET Framework 4.6.2 by default (but I specified it in the LabVIEW.exe.config file as well). 

Here are the namespaces of the 2 .NET controls

System.Windows.Forms.SplitContainer

System.Windows.Forms.Panel

Other than System.Windows.Forms no other namespaces were used in my library.

Here is where I had the files:

C:\Program Files (x86)\National Instruments\LabVIEW 2019\user.lib\ImportDotNetLib.vi

C:\Program Files (x86)\National Instruments\LabVIEW 2019\vi.lib\ClassLibraryEven.dll

I tried putting them both in the same folder but that didn't work either.

Someone posted somewhere that the name of the class in the library must match the name of the dll file.  I don't know if that's true but I did it that way.

 

0 Kudos
Message 1 of 6
(3,746 Views)

I can see from the ".NET Assemblies in Memory" option under the "View" menu heading that LabVIEW has loaded the System.Windows.Forms.dll library from the GAC which is version 4.8.44 but my dll and LabVEIW 2019 are both supposed to use version 4.6.2

 

I've tried lots of ways to force LabVIEW to use the version I need (4.6.2) instead of the version in the GAC but nothing seems to work.

0 Kudos
Message 2 of 6
(3,703 Views)
Solution
Accepted by skinnedknuckles

I made it work by skipping the panel and adding the split container directly to the .NET container.  I seem to be able to call public .NET methods and properties from LabVIEW without any trouble (click on the first 2 buttons to see this work) as long as the control itself was originally created (constructed) in LabVIEW.  So the only limitation I'm left with is not being able to use the .NET constructors.  Maybe some magic can be found using variants or anonymous types.  Otherwise, I'll have to wire objects created in LabVIEW to the Constructor Node and then I can do what I want with them using the invoke node and property node functions in the .NET subpanel of the Connectivity Pallet in LabVIEW.  If LabVIEW can't work with .NET constructors, that might explain why they created the "Constructor Node" function. 

Download All
0 Kudos
Message 3 of 6
(3,668 Views)

When embedding .Net controls in a .Net container in LabVIEW you do not use a constructor explicitly. Instead you assign a specific .Net class implementation to the .Net container and LabVIEW then calls the constructor automatically. Basically the .Net container is itself the object constructor. There is one specific difference though. The .Net container gets initialized at initialization time of the VI (usually at load time when you run your program), which means that the .Net class gets loaded then, as there is no explicit constructor that gets executed somewhere at runtime.

 

Your attempt to assign a LabVIEW object to a panel property of your .Net component could never work. A LabVIEW object is NOT a .Net class but something totally specific to LabVIEW. The .Net container does internally use a Windows window handle that is passed to the .Net control at initialization time to tell it where it is allowed to draw itself into but that is a private implementation detail of the .Net container.

 

But you are aware that LabVIEW also has native pane splitters? .Net containers should always be your last resort to try to solve something. It's a .Net feature that Microsoft did implement as otherwise nobody would have wanted to abandon ActiveX in favor of .Net. But just as Microsoft nowadays wishes that they could make ActiveX totally disappear from the world if they could, they also rather would wish .Net containers were never invented. It is one feature that is almost impossible to properly implement multiplatform, which would be a requirement if they want to support .Net controls in .Net Core.

 

And just as ActiveX controls, it is always wrought with troubles. No matter how many guidelines, howtos, and dont's Microsoft releases about creating correct .Net controls and .Net control hosts, the majority of them only implements just enough that the programmer can pull his hands away and yell "Mom look it works" and then forget about it!

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

Hi Rolfk,  Thanks for your reply.  You seem to have a good understanding of this topic so I especially appreciate your perspective.

 

However, I'm not sure what you mean by "panel property".  I used "panel" to mean the .NET object of the System.Windows.Forms.Panel class.  But I think we are both saying the same thing perhaps from different perspectives.  I know LabVIEW has a pane splitters but I don't want to bore you with my interest in using .NET controls instead.  It seems we agree on at least 2 things.

  1. Clearly publically declared methods and properties of .NET objects can be invoked in LabVIEW for .NET objects that were added to the .NET container from the .NET sub pallet (or with "Insert .NET Control").  This is assuming LabVIEW has acess to the required .NET libraries added to the project or already in the GAC.
  2. The code attached in the reply marked "solution" shows that publically declared .NET properties and methods of a .NET Class Library built with Visual Studio can also be invoked in LabVIEW for .NET objects that were added to the .NET container from the .NET sub pallet (or with "Insert .NET Control").  This is assuming LabVIEW has acess to the required .NET libraries added to the project or already in the GAC.

But there remains some confusion perhaps due to semantics.  It seems the phrase ".NET Contructor" is sometimes used in reference to the "Constructor Node" function of the .NET subpallet under the Connectivity pallet in LabVIEW shown below.

 

LabVIEW .NET ConstructorLabVIEW .NET Constructor

 

  Other times the phrase (more correctly I would argue) ".NET Constructor" is used in reference to the constructor method of a class in the C# (or VB.NET) code shown on line 11 below.

 

.NET Constructor.NET Constructor

 

Am I correct to say that the first one works in LabVIEW and the second one will not work in LabVIEW even if it is part of a proper .NET class library built in Visual Studio?

 

 

 

 

0 Kudos
Message 5 of 6
(3,629 Views)

@skinnedknuckles wrote:

 

Am I correct to say that the first one works in LabVIEW and the second one will not work in LabVIEW even if it is part of a proper .NET class library built in Visual Studio?


Not really. The constructor of a .Net class is called by LabVIEW through the Constructor node when you "construct" an object to be used as class library. The runtime execution of the LabVIEW constructor node is pretty much the same as the .Net statement (plus some LabVIEW related management): 

 

objectRef = new MyClass();

 

By far most of the .Net classes used in LabVIEW programs are simply libraries that implement one or more classes with methods and properties and no user interface facing part of any sort.

 

 

In order for a .Net object class to be insertable in the LabVIEW .Net container, it needs to implement the System.Windows.Forms.Control interface or some derived class of this.

 

LabVIEW will initialize the object implicitly when it loads the VI containing a .Net container with an assigned .Net Control class. It will also call the Control objects constructor at that time and you do not need (and shouldn't try) to call the constructor yourself by using the Constructor Node. It would simply load another instance of that class but without any connection to a LabVIEW container in which it could display itself. The Control class is already constructed by the time the VI containing that container has finished loading into memory.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 6 of 6
(3,624 Views)