LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Updating ActiveX Types when Changing from 32-bit to 64-bit

Solved!
Go to solution

I'm using an ActiveX in LabVIEW. Everything is working fine using the Automation Open, calling the methods and so on. The ActiveX exists both in a 32-bit and a 64-bit version. I created my initial VI using the 32-bit version to begin with. Then I saved my VI and launched the 64-bit version of LabVIEW and opened the VI. Since the class name is the same for the ActiveX in both 32-bit and 64-bit I expected the VI to run in 64-bit using the 64-bit version of the ActiveX, but it doesn't. It seems that 64-bit LabVIEW "remembers" the 32-bit version of the ActiveX. What I e.g. could see is that the numeric format of the data was still I32, when the ActiveX in 64-bit version is using I64?

 

What I have to do, to make it work, is:

* Re-select the ActiveX class in the Automation Open VI

* Re-select all methods using browse.

 

My question is now, since the class name, and all the methods in the ActiveX are exactly the same in 32-bit and 64-bit, so why can't LabVIEW automatically reload the ActiveX using the correct types?

Is there a function in LabVIEW to refresh all classes and methods?

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

There's an old saying, "If It Ain't Broke, Don't Fix It!".

 

64-bit LabVIEW is getting better.  However, if you do not need the addition PC memory addressing space, why migrate from 32-bit LabVIEW, which seems to work, to 64-bit LabVIEW (which is still playing "catch-up")?

 

Bob Schor

0 Kudos
Message 2 of 6
(3,315 Views)

Well, I agree, but the problem is that we provide the ActiveX and many of our customers seems to prefer the 64-bit LabVIEW. (Maybe LabVIEW 64-bit is installed by default on 64-bit Windows?)

 

And we would like to have only one sample VI that can be used on both 32-bit and 64-bit LabVIEW.

 

-cpede

0 Kudos
Message 3 of 6
(3,311 Views)

you misunerstand something here. The Class name has little to do in what ActiveX Autionation servr DLL gets loaded. ActiveX works differently. (.Net too but there the class loader has been changed to work in a different way).

 

An ActiveX server is located in two ways. One possibility is by its Automation name in the registry. That is seldom the Class Name, although it could be. And it needs to be different for 32-bit and 64-bit since ActiveX was introduced long before anyone thought about 64-bit software so there are not two seperate registry hives, one for each bitness. The registry entry then contains a path that points to the DLL that implements the ActiveX server.The other possibility is to directly load the DLL by pointing the Automation Open Node at the DLL In both cases the VI remembers the DLL to load and the class name only matters after that for the case where an ActiveX server implements multiple classes.

 

Now ActiveX also supports out of process marshalling. This is similar to DCOM where you can execute an ActiveX server on a different machine and Windows then marshals all the data over network or whatever the connection is.The input parameters of every function call are send over the network in a stream to the servr and the return values are then send back in the same way back and appear at the caller just as if he had called the server locally.

 

If the ActiveX invocation detects that the ActiveX server is a different bitness than the caller, it also does something similarr. It invokes the ActiveX server component out of process in a proxy process and sends all the parameters through a pipe or network connection to it and receives the return values to hand back to the caller. This can also happen if the ActiveX invocation detects that the threading model of the server component is not compatible to the caller threading model. As such your 32-bit ActiveX compononent can usually be called from a 64-bit LabVIEW process just fine although performance could be suffereing, since all the data has to be marshalled through a network or pipe connection.

Rolf Kalbermatter
My Blog
0 Kudos
Message 4 of 6
(3,289 Views)

Thanks for the answer. Actually the problem is more basic, I will try to illustrate it by a simple diagram.

 

I have only one VI looking something like the attached image.

 

1) When creating it and opening it in 32-bit LabVIEW the handle returned by the Connect method is a I32.

 

2) When opening it in 64-bit LabVIEW the handle is still a I32. However if I reselect the class using the left most object right-clicking Select ActiveX class and Browse and reselecting the same class object AND go to the Connect object right-clicking Select Method and Browse and reselecting the same method the handle becomes I64, as expected.

 

Since the class names are the same in both 32-bit and 64-bit, Windows correctly handles this in two different Windows Registry hives, and this seems to work perfectly for other programming languages and environments. What I'm trying to achieve is to limit my samples to only one VI, which can run in both 32-bit and 64-bit LabVIEW without having to create two identical VIs.

 

So my question are:

Why do I need to reselect all classes and methods before LabVIEW understand the types?

And is there are function in LabVIEW to refresh everything so I don't have to go through all methods?

 

-cpede

0 Kudos
Message 5 of 6
(3,262 Views)
Solution
Accepted by topic author cpede

Unfortunately for you, what I said is still valid. ActiveX is based on COM, with the addition of a required typelibrary, describing the binary invocation interface of the exported classes (and a few other details that are irrelevant for the moment).

 

COM class servers are instantiated through a CLSID through CoCreateInstance(). It is this CLSID that LabVIEW together with the IID for the COM object class itself that you selected, stores in the Automation refnum and which ultimately identifies both the actual COM server DLL and the according ActiveX type library (which usually are combined inside the same DLL, but don't have to be).

 

The LabVIEW object browse dialog is simply a convinience function so you do not have to remember and type in GUIDs, which are unwieldy 16 byte binary blobs. It enumerates all registered ActiveX objects and displays them with their registry names (which often can be rather uninformative but that is not LabVIEW's fault) and lets you select the one you want. At this point you make the selection which class server is invoked. LabVIEW takes the associated CLSID from that registry entry and stores it in the refnum descriptor together with the IID for the class interface you selected. From now on this refnum refers to this specific CLSID/IID which is unique and only applies to this specific ActiveX server, including its bitness.

 

This may seem a bad implementation but it has both historical reasons as well as practical ones. Historically LabVIEW was a fairly early adopter of ActiveX. Many things of how to use it weren't very clear in the beginning. Also Windows had everything needed to use it, but many convinience functions didn't exist or were undocumented back then. LabVIEW's way of enumerating all the ActiveX objects in the registry rather than using a qualified ProgID name most likely comes from the fact that not all ActiveX objects were registered with an OLE1 ProgID, so if LabVIEW had relied on that, many ActiveX objects could not have been used in LabVIEW (but the ProgID names would be easier to match with Visual Basic examples, which usually use this ProgID to invoke an ActiveX server).

 

Anyways your problem is that the CLSID for the ActiveX object is defined at the moment when you select that ActiveX object in the browse dialog (or directly select an ActiveX DLL on disk). Changing LabVIEW bitness does not reevaluate that CLSID later on since there is no identifying information stored in the Automation refnum in the form of an OLE1 ProgID to do this.

 

And this was almost never a problem in the past, thanks to the OLE out of process invocation feature of ActiveX that simply instantiates the ActiveX object in a proxy process when something in the process model of caller and callee doesn't match. This includes threading and bitness differences. Because of this there was never a pressing reason to change the way LabVIEW refers to ActiveX components and by doing that introduce incompatibilities with earlier LabVIEW versions. And in the meantime, ActiveX has become a very legacy technology that Microsoft tries to marginalize in favor of .Net at every opportunity, so the chances that the LabVIEW developers will ever go and redesign anything about their ActiveX handling is pretty much non-existent. The next change in ActiveX functionality in LabVIEW, if any ever happens, is more likely the removal of ActiveX support altogether than anything else!! I'm not saying that it is going to be removed here, just that the chance for that is significantly higher than any kind of redesign of the ActiveX functionality.

 

There is likely a possible workaround for your library here. It will involve using a conditional compile structure and the creation of two ActiveX refnum typedefs. Browse to your ActiveX implementation in LabVIEW 32-bit for one of them and to the same ActiveX implementation in LabVIEW 64-bit for the other one. Then place them in the respective Conditional Compile structure frame. Then wire the output of that to Automation open. Although thinking that further it won't quite help with that since the ActiveX refnums in your VIs to pass the refnum along still will refer to only one of them. It would mean that you have to replace all ActiveX refnums in your library with a generic refnum (for instance a file log refnum with an enum dropped in to make it a unique refnum) and in each VI typecast the incoming generic refnum to your conditional compile refnum, pass it to the ActiveX nodes and then typecast it back to the fake refnum to pass out of the VI.

 

This is basically what you would have to do in all your subVIs for your library. I would make all the refnums a typedef (also the hidden 64-bit one) but didn't here as that would make the snippet not work.

Auotmation Refnum Bitness.png

 

How you will handle the difference in datatypes that the nodes take will depend on your library. There is certainly a chance that you may at some points have to use the conditional compile structure for that too.

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 6
(3,251 Views)