VB6 ActiveX EXE

Components provide reusable code in the form of objects. A VB6 application that uses a component’s code, by creating objects and calling their properties and methods, is referred to as a client. And the DLL that exposes those components is referred as the server.

Components can run either in-process or out-of-process with respect to the clients that use their objects. An out-of-process component, or ActiveX EXE, runs in its own address space. The client is usually an application running in another process.

Client and out-of-process component

An ActiveX EXE usually define classes and these classes can have different instancing settings:

  • Private: this is a class that is only used internally by the server. In other words, you don't want to make this class available in any way to your server's clients. If you set the class's Instancing property to Private, no applications outside your server can see this class or instantiate objects from it.
  • PublicNotCreatable: this signifies that an object of this class is visible to a client, but that the client can't create such an object directly.
  • SingleUse: a SingleUse class can only supply one instance of itself per copy of its server. Assume that your COM server has two SingleUse object classes, ClassA and ClassB. If two clients want to instantiate copies of ClassA from your server at the same time, ActiveX runs a second instance of the server each time an instance of ClassA is created. If one client wants to instantiate a copy of ClassA and another client wants to instantiate a copy of ClassB, however, ActiveX will allow both of them to use the same copy of your server, as long as each object instance is the first requested instance for each class. If your project had a startup object like for example a Sub Main, that means that for each time a new SingleUse instance is create and a new server is spawned then the main object (sub main) will be executed.
  • MultiUse: this means you can create multiple instances of a MultiUse class. The first request for a class instance starts the COM component. All subsequent requests are serviced by the already running server. If a client application requests several instances of a ClassA, for example, one server creates all instances of ClassA. This concept is very important. Remember that an ActiveX EXE runs out process, so that means that only one server will be created in this process.
    This is important if you setup a start up object. Because that means that when you create the first instance the Startup object (Main for example) will be called because the server is being initialized. After the first instance is created you will have no further calls to the main method.
  • GlobalSingleUse or GlobalMultiUse: a global class does not require a client to explicitly instantiate it before the client tries to use it. In other words, if a Global class exists in a server application that a client is referencing, the client can manipulate the Global class methods and properties as if they were just Public variables and procedures of the client. Also is a class is Global SingleUse or MultiUse then the same observation for SingleUse or MultiUse apply.

 

ActiveX EXE Conversion

The VBUC will identify if your project is an ActiveX EXE. In your solution list it will mark its type as OleExe and the Reference Guid is the Guid that is used in other projects to reference this ActiveX DLL.

The VBUC provides at least 3 migration options:

  • .Net Assemblies with COM Visible

The VBUC converts Visual Basic 6 ActiveX Dlls to .Net assemblies.  By default the resulting .Net assemblies can be used only from managed code. If it is necessary use to these assemblies from non-managed code, this option should be selected in order to generate the .Net attributes required to expose these assemblies as COM Objects.  For example: [ComVisible(true)].

In addition to the ComVisible attribute for the assembly members, the .Net project is also marked as a COM Visible.

The exposed classed will also have the necessary COM attributes added. For a source code example see here.

However in this approach no OutOfProcess support is provided. If you need this Dll to run out of process you can use a DllSurrogate

The DllSurrogate is setup in the Registry. After you register your assembly for COM

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe Assembly1.dll /codebase

you need to add two registry entries. For example:

C# Source Code

    [ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
[GuidAttribute("FF98BA94-FFFF-3D4F-9D11-BC6DE81D33EE")]
public class ComServer {
// Rest omitted
Then add two entries like the following:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\AppID\{FF98BA94-FFFF-3D4F-9D11-BC6DE81D33EE}]
"DllSurrogate"=""

[HKEY_CLASSES_ROOT\CLSID\{FF98BA94-FFFF-3D4F-9D11-BC6DE81D33EE}]
"AppID"="{D698BA94-AEFF-3D4F-9D11-BC6DE81D330B}"
This approach is also useful if you want to migrate your project to 64 bit 
but still use it from your 32bit legacy code VB6

  • Out of Process and Application Domains using Helpers Classes

    This optional feature enables the conversion of ActiveX DLL/EXEs (with global variables) via a helper class (ComponentClassServer) that controls the instantiation of the generated class libraries.

    ActiveX DLLs   are converted to .Net using application domains and the instantiation of the components is archived using helper classes.

    With this approach most of the ActiveX functionality is replicated in the converted code. For more details and sample code click here.

  • Standard .Net Assemblies

Converts ActiveX DLL/ and ActiveX EXEs to standard .Net assemblies (class library projects).

Remarks:

All ActiveX are converted to native .Net assemblies.

With this approach the converted code can be use only from manage code and the different VB6 ActiveX instantiation models (e.g MultiUse, GlobalMultiuse, etc) won’t be supported.

The VBUC converts Visual Basic 6 ActiveX EXEs ActiveX DLL to standard .Net assemblies (class library projects).

One of the main differences between VB6 ActiveX and .NET assemblies is the way of how the component is instantiated (e.g MultiUse, GlobalMultiuse, etc). This initialization determines the lifetime behavior for the component. With this option the code is converted using pure .NET code and the VB6 ActiveX instantiation models won’t be supported.