by Jim Karabatsos - GUI Computing
When you create an ActiveX component of whatever type, one of the new issues that you will have to deal with is how to maintain compatibility as you progress through the development of your project and, more importantly, across future versions.
By default, VB5 will generate a new set of GUIDs whenever you compile or run your component. (This is actually quite wasteful of GUIDs -- at this rate we will exhaust the supply of GUIDs within the next billion years or so!) As long as you are looking at the component in isolation, this causes you no problems.
Of course, the whole point of creating ActiveX components is so that they can be used by a client application, either your own or by some third party. As soon as you do that, however, you need to ensure that your component can be revved without breaking all the clients that depend on it. One of the important aspects of your component that must not change is the set of GUIDs in use, as well as the definition of each of the methods of the component.
Fortunately, VB5 has a mechanism whereby you can specify that it should create a compatible version of the component -- that is, it should re-use the existing set of GUIDs and ensure that all methods of each interface remain in the same order and maintain their previous parameter and return types. You can find this option under Project|projname Properties... in the VB5 IDE. You need to set "Binary Compatibility" and point the system at the file you want to remain compatible with. Don't let the "Project Compatibility" option fool you -- it should have been called "Project Incompatibilty" and it will not generate compatible components.
As long as you are creating DLL-based ActiveX components, the way most people use this is to identify the DLL/OCX itself as the source of the compatibility. Sure seems to make sense and it does work.
The problem is that this same technique does not work for ActiveX EXE servers. If you set the options for compatibility with the EXE name you are trying to compile, you will get a link error telling you that it was unable to write to the EXE file.
Now maybe I'm just slow, but this had me going for longer than I care to admit. It actually does make sense, but it may not be obvious at first (it sure wasn't for me).
You see, in order to ensure that the new project maintains compatibility, the VB compiler needs to open the old version in order to access the type library inside. It can then check that the new version is indeed compatible with the old version as it compiles. When compilation is finished, it proceeds to link the modules and create the executable. The problem is, it forgets to close the type library first and so the linkage step fails because it cannot overwrite the executable that contains it.
Obviously, the way VB compiles a DLL-based server is a little different and, by the time the linker gets to do its thing the type library (and hence the EXE) is no longer locked by VB. I'm not sure why this is the case, but I suspect that this is related to the fact that VB plays fast and loose with the registry in order to make it possible to test and debug ActiveX DLL servers.
When you "run" an ActiveX DLL in the IDE, VB5 actually fiddles the registry to make itself an out-of-process ActiveX server for each of the classes contained in the DLL. If you think about it, this is the only way it could manage to let you debug the DLL (short of VB5 becoming an in-process server -- shudder!!!). I suspect that what is happening is that in the course of these shenanigans, VB5 generates a temporary, stand-alone type library and points the registry at that; my guess is that once this temporary type library exists VB uses it for compatibility checking and closes the DLL, making it possible to compile over the compatibility source.
So, how do you actually get compatibility to work for ActiveX EXE servers?
It turns out to be quite simple (it may even be in the manuals, but of course you can't actually leaf through a CD). The trick is to make a copy of your EXE server and point to that copy as the compatibility target of your project. I just used the Win95 Explorer to make a copy (I even left it named "Copy of MyServer.exe") and then changed the project compatibility options to point to that file. That's all it takes to make it possible to compile a compatible version of your ActiveX EXE servers. The same technique will also work with other types of ActiveX projects; personally, I think I'll train myself to do this in all cases.