Posts Tagged ‘ActiveX’

Avoiding possible problems caused by .NET controls exposed via ActiveX

Wednesday, August 14th, 2013

Microsoft .Net Logo (Source File, .jpg)zenon allows the use of ActiveX controls for extending the user interface. A series of Information Unlimited articles shows how such ActiveX controls can be created using a .NET Framework programming language. As the .NET Framework is managed code, the .NET ActiveX controls are  destroyed by a garbage collector at any time if the reference count reaches zero. Additionally, the garbage collector must recognize that the ActiveX control is not referenced by any other object in order to be able to destroy it. This managed way of destroying .NET ActiveX controls can lead to serious problems.

Problems that might occur with .NET ActiveX controls with a simple user interface

One problem that might occur is that there is no garbage collection between closing a screen in zenon Editor and closing zenon Editor itself. A .NET ActiveX control that hasn’t been destroyed when zenon Editor is closing causes the zenon Editor process to remain active after closing the zenon Editor window. Since there can only be one running zenon Editor instance on a computer, this leads to problems when zenon Editor is started again:

  • If it is started by a different user, the user trying to start zenon Editor will receive an error message that another user is currently using it although the other user has closed zenon Editor.
  • If it is started again by the same user, zenon Editor will show up immediately but without a workspace loaded. If the user then tries to load a workspace, zenon Editor crashes, because it is in the terminating state after hiding the main window and therefore no longer ready for user interactions.

In zenon Runtime this problem also might occur, but zenon Runtime terminates after running through its teardown routines without waiting for garbage collection of .NET ActiveX controls.
To fix this issue, garbage collection is triggered on closing screens in zenon 7.10 and higher.

Problems that do occur with .NET ActiveX controls with a complex user interface

But what happens if the garbage collector cannot recognize an object as deletable and when does this occur? If a .NET ActiveX control reaches a certain user interface complexity (child controls nested in other child controls, event handlers for those child controls and object members holding a reference to the control), the garbage collector cannot recognize the control object as deletable after the screen hosting it is closed. If that occurs, the problems described above will occur, in addition to leaking memory every time a screen with such a .NET ActiveX control is shown. As the mentioned fix only triggers garbage collection, it does not resolve problems caused by such .NET ActiveX controls.

So what can be done to resolve this problem (apart from not using .NET ActiveX controls)? First of all, it is recommended to avoid instance members holding a reference to the control wherever it is possible. If there is no way to avoid such members, they have to be cleared in the same method where the user interface is cleared (see below). As it is the complex user interface that prevents the garbage collector from destroying the object, the user interface objects must be cleared when the user interface is no longer needed. This can be done by implementing the .NET ActiveX control methods

zenOnExit

and

zenOnExitEd

and calling

Dispose

in both those methods. The following code sample is given as an example:

public bool zenOnExit()
{
Dispose();
return true;
}
public bool zenOnExitEd()
{
Dispose();
return true;
}

With this knowledge it is easy to avoid the described problems by simply including the two zenon exit methods in every .NET ActiveX control that is used.

How about using ActiveX-controls in 64-bit zenon?

Wednesday, June 12th, 2013

64-bitIn some projects ActiveX-controls are used for custom GUI objects rather than creating them from standard zenon screen elements. Usually these ActiveX-controls are written in VB6 or C++. All these ActiveX-controls are 32-bit components and cannot be used in 64-bit applications out of the box. But under some circumstances it takes only some simple modifications to make them run in 64-bit aswell.

Background

ActiveX-controls in principle are DLLs with a standardized COM interface. So they are in-process COM-servers and are loaded directly into the host application process. Now, fact is that generally a 64-bit application is only able to load 64-bit DLLs. So 32-bit ActiveX-controls cannot be loaded by 64-bit zenon. To make this possible, the 32-bit ActiveX-control must be ported and compiled into a 64-bit DLL.

Bad news

Unfortunately the previous VB6 is not able to generate 64-bit output. So there is no way of bringing a VB6 ActiveX-control into 64-bit zenon except by rewriting it completely in C++ e.g. If it is absolutely necessary to keep them, one must stick to 32-bit zenon even if the used platform would offer using the 64-bit version. The same is true of course, if you do not have the source code at all and only have the 32-bit binaries.

Good news

If your ActiveX is written in C++ and you have the source code, you can easily introduce a second x64 configuration into the project and compile a 64-bit AcitveX-control then. Usually there are no or only minor changes necessary in your source code that make it run again in 64-bit. And please don’t forget to also register 64-bit ActiveX with regsvr32 afterwards. 32-bit and 64-bit ActiveX-controls are registerd in different registry paths, even if they have “the same control” with the same CLSID and name.