Reputation: 15807
When I started university Java and .NET were the technologies used for teaching.
I have familiarized myself and gained experience with COM (Component Object Model) based languages like VB6 over the last three years. I understand the difference between COM based languages and more modern languages at a high level.
I don't understand what is happening in the Registry. For example, I execute the following command:
regsvr32 myDLL.dll
I can then find an entry under: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID. Is this the only entry that is made for a VB6 program? For example, if I did the following then would the DLL still be available:
I have tried this and it did not work.
Upvotes: 1
Views: 627
Reputation: 941635
Regsvr32.exe is a very simple program, it does very little to contribute to the registration itself. It simply uses LoadLibrary() to load the DLL whose name you passed as an argument, then GetProcAddress() to locate an exported function in the DLL. Which is DllRegisterServer(), if you use the /u option to unregister then it goes looking for DllUnregisterServer(). And calls the function, that's all.
DllRegisterServer was written by the component author. Exactly what it does is unpredictable, anything is possible. But there certainly is commonality, its intention is to write registry keys that the component needs to be usable from another program. You'll want to use SysInternals' Process Monitor, its trace shows exactly what is being done.
You already know about the HKLM\Software\Classes\CLSID\{guid}
registry key. Very important, this is what powers the CoCreateInstance() call in a client program. Which creates an object in the server by simply specifying a number (the CLSID), the COM infrastructure ensures that the correct DLL is located and loaded, its DllGetClassObject()
entrypoint is the factory function that supplies the object.
Core feature is that the client program doesn't have to know anything about the DLL itself, all it does is supply a number and it magically gets an object created. Which provides lots of flexibility in how the DLL is constructed with no dependency at all on the language in which the DLL source code was written. A feature that for example is taken advantage of when you write a [ComVisible] .NET component, a language like C# doesn't support exporting functions like DllGetClassObject(). Still works (a bit out of scope), the client is completely oblivious about the plumbing in the CLR that makes it work.
Almost any COM server's registration function writes these keys:
HKLM\Classes\Software\CLSID\{guid}\InprocServer32
. Written for each coclass implemented by the server. The default value of this key contains the path to the DLL. Tells the COM plumbing which DLL to load to find the DllGetClassObject entrypoint. An out-of-process server (an EXE instead of a DLL) uses the LocalServer32 key instead.ThreadingModel
value in CLSID. Specifies the threading requirements for a COM object. Very common is "Apartment", tells the COM infrastructure that the COM object is not thread-safe and that COM should take care of calling the functions inside the server in a thread-safe way. Other common values there are "Both" (the default for .NET components) and "Free", written for components that can handle calls from worker threads by themselves.HKLM\Classes\Software\Interface\{guid}\ProxyStubClsid32
. Written for each interface implemented by a COM coclass. Required for any COM object that is not free-threaded, contains the CLSID of a COM object that knows how to marshal calls on the interface methods from one thread to another. A very common value you find there is {00020424-0000-0000-C000-000000000046}, the default marshaller that's included in Windows and knows how to marshal calls based on the content of the type library. A custom one is not unusual either, particularly for a COM server that was started by describing the interfaces in the IDL language. The proxy/stub for such a component can be auto-generated from the IDL.HKLM\Classes\Software\Interface\{guid}\Typelib
. Present for servers that depend on the standard marshaller, the default value is the guid of the type library.HKLM\Classes\Software\Typelib\{guid}
. Present for servers that depend on the standard marshaller, tells COM where to find the type library it needs.HLKM\Classes\Software\{progid}
. Pretty common for servers that support late binding, allowing them to be used from a scripting language like Javascript or VBScript. Where {progid} is a friendly string to identify the component instead of a guid. Powers the CreateObject() runtime support function present in many languages. The CLSID subkey in this key tells the runtime which guid it should use to locate the CLSID key.You may see many more keys being written. An ActiveX component writes a bunch of keys in CLSID to pass info to the host application and a programming tool like VB6. A server written in .NET adds several keys to help the CLR locate the assembly that contains the [ComVisible] component.
Upvotes: 10
Reputation: 13267
Remember that regsvr32 is not magic. It loads the target DLL (or OCX) and invokes the self-registration entrypoint of that library. This normally produces bare-bones registration of one or more classes, ProgIds, and the type library, which is embedded in such DLLs whenever the VB6 compiler produces one. An ActiveX EXE performs self-registration in a similar manner but not via an external caller. Instead a special run of the EXE is done, passing the regserver
command line switch.
Self registration is not the preferred way of installing any of these things on target systems. It is just the minimal, bare bones of registration that the compiler can generate without needing to read the developer's mind. It also completely skips over making vital servicing entries in the registry such as uninstaller links, creating/incrementing usage counts, and the like. And it can't produce tons of other registry entries the code may rely on (shell extension info, data file type/extension association, service information, DCOM activation parameters, etc.).
Other compilers offer the option of creating type information in a separate typelib file but VB6 does not.
So what you propose is reasonable but misses many things. Just to begin with you have omittted the type information (typelib) registration found under HKEY_CLASSES_ROOT\TypeLib\
but there is also ProgId information under HKEY_CLASSES_ROOT\
, and so on.
See INFO: Registry Entries Made by an ActiveX Component for a little more information.
Remember VB6 doesn't create raw COM components but ActiveX components, a superset of COM adding aspects of OLE2.
.Net relies on a more primitive Java-like mechanism based on file location, unless you GAC assemblies (a .Net version of registry publication).
Upvotes: 1
Reputation: 175826
I can then find an entry under: HKEY-Local-Machine-CLSID. Is this the only entry that is made for a VB6 program?
No, there are multiple entries; for example \TYPELIB
and SOFTWARE\CLASSES\PROGID
where PROGID
is the YourSever.YourClass
identifier.
When you unregister your component these will be deleted so reimporing the CLSID key will not restore functionality.
If the type definitions are not stored in the file (before they are registered), then were are they stored?
A COM DLL can store it's type library internally as a binary TYPELIB resource.
Upvotes: 2
Reputation: 2786
While .NET assemblies contain their type definitions (classes, methods etc.) directly in the generated .EXE or .DLL file, COM components do not and therefore need to be "registered" first to be identified.
The registration and unregistration process runs independently from the stored .DLL-file. So unregistering a COM component doesn't remove the .DLL-file, but just removes the information used to identify it.
Upvotes: 0