What does DllRegisterServer generated by the VB6 compiler do? - com

When you compile a VB6 DLL the compiler adds an exported DllRegisterServer() function to the DLL.
What exactly does this function do?
I do understand that its purpose seems to be to add entries to the registry that allow all the COM magic to work... calling it
"Instructs an in-process server to create its registry entries for all
classes supported in this server module."
But I am interested in a specific, detailed specification for what it does. I haven't found any MSDN documentation on this. Does something like that exist? Has anyone disassembled that code and documented their findings?
Edit: One reason I'm interested in this is that I think there are cases where it doesn't work fully / successfully (even when regsvr32 reports success) and I'd like to understand these potential failure modes better.

The function is used to register the DLL with the windows registry. For example, if you call regsvr32.exe with the DLL name, the DLL will be loaded and then the regsvr32.exe utility will call the DllRegisterServer() function. What the function ought to do from a COM perspective is to make the PROGID, CLSID, and TypeLib entries in the Windows registry so that COM clients can create and use the COM object through CoCreateInstance().

Related

Check whether a DLL is registered using Inno Setup

My setup that I created using Inno setup mainly registers some DLLs.
Now I would like to add some conditional behavior. A certain path shall be taken if another DLL is installed/registered on the system.
Is it possible to use Inno setup to detect whether a certain DLL is registered in Windows?
The DLL I want to check is not from me. The only thing I know is its name, but I don't know about any COM objects or CLSIDs.
There's nothing like "DLL registration" as such. Only COM objects are registered. So you have to know, what COM objects the DLL does register; and then check for those.
Only other thing you can do, is it to traverse whole HKEY_CLASSES_ROOT looking for an entry with the DLL. But that may take tens of seconds even on a fast machine.

Where Clsid comes from when registering COM

When I register COM dll by running regsvr32 MyCOMdll.dll in CMD I see several entries created in registry, one of them is:
[HKEY_CLASSES_ROOT\MyCOMdll.MyClass\Clsid]
#="{DB402D5A-5584-4F68-A750-45D3E8133121}"
I'd like to understand where DB402D5A-5584-4F68-A750-45D3E8133121 comes from, initially I thought that GUID generated at point when you register this DLL, however I checked this at different environments and I see it has same value. It looks like these GUIDs are embedded into DLL, but I cannot confirm or find out at which point.
Context: I want to perform a "hot swap" of that COM, however it doesn't seem to be straightforward. I tried to update GUIDs in registry after I register new DLL, but getting error ClassFactory cannot supply requested class.
When you register a COM dll using regsvr32, CLSIDs are defined inside the dll.
In typical ATL COM project, these entries are specified in *.rgs files, and registry is updated based on that content. Of course, this is not the only way to do it and other toolsets and technologies do it in different way.
These CLSIDs are actually defined in the .idl file of the project (again, this is valid for ATL projects), and .rgs file must correctly match the values. The .idl file itself contains IDL definitions of all COM types in the library, and is used by MIDL compiler to generate the type library.

Registered COM DLL works in VBA but not in VBScript

I have created a basic COM DLL with ATL on VS2012. It's called testCOM.dll and it only has one class called CSimpleObj. CSimpleObj has just one method called addValues which adds two values.
I've registered the DLL with Windows 7 64-bit. In VBA, I manually add a reference to the DLL and the below code works properly
Dim Obj As New testCOMLib.SimpleObj
MsgBox Obj.addValues(1,2)
And it give a message with number 3.
Now If I run the vbs which includes:
Dim Obj
Set Obj = CreateObject("testCOMLib.SimpleObj")
It constantly gives an error and is not able to create the object. But if I use the "Excel.Application" ProgID (as an example) for the CreateObject method, it works fine.
I think there is an issue with registering the DLL. I've checked the registry, and the keys for the COM and the type library is already there.
What should I do?
There are three basic requirements to get your COM server to be usable from VBScript:
You need to implement IDispatch so late binding is supported. Not usually a problem with ATL, it implements it by default when you use the wizards.
Your registry script (.rgs) must write the ProgId to the registry. Notable is that you didn't report finding it (look for HKCR\testCOMLib.SimpleObj with Regedit.exe to verify). Its CLSID subkey must match the CLSID in the registry so COM can find your DLL. The ATL Simple Object wizard has a trap, it fills in all the fields when you type the short name. Except for the ProgID field. So very easy to forget.
On the 64-bit version of Windows, you'll execute the 64-bit version of cscript.exe by default. It will not be able to find your 32-bit COM server. You'll need to either build the x64 version of your server or you'll need to use the 32-bit version of cscript.exe, located in c:\windows\syswow64. Not usually a problem with VBA since it tends to be used from a 32-bit version of Office.
The SysInternals' Process Monitor utility is very useful to diagnose these kind of problems. You'll see cscript.exe searching the registry for the keys that your server registered. And probably not finding them, you were however not explicit enough about actual error message you got.

Interacting with a specific COM DLL

I'm trying to interact with a .dll which will allow me to receive information from a variety of devices (Eye Gaze to be specific). The .dll is called ETUDriver and can be found at http://www.sis.uta.fi/~csolsp/projects.php however it does not come with an accompanying .h file.
I am struggling to actually load, interact and invoke functions from the .dll. A manual is supplied but it is of no help whatsoever with regards to actually setting up the code to start it off. There are three accompanying example apps (with source code) but only two of these work and one of which is in C# so is not helpful. The one that works however loads up the .dll via MFC and this is not a viable option with my code (which is intended to be used with many other projects and as such can't enforce MFC or any other libraries that are not as standard to projects).
Essentially, within the .dll is a series of classes which I need to create within my code and invoke the relevant functions of that class.
I've tried to use HRESULT hr = CoInitialize(NULL);
hr = CoCreateInstance(__uuidof(ETUDSink), NULL, CLSCTX_INPROC, __uuidof(IETUDSink), (LPVOID*)&pETUDSink);
if(pETUDSink)
{
pETUDSink->Start();
} however it always returns an error saying that the class is not registered. I can't use MFC to call the relevant .rgs file and am completely stuck on how to get this to work otherwise.
Is there a given format to doing this that I am unaware of and has anyone had experience in using the ETUDriver (or is able to get it working in C++ without use of MFC)?
Thank you for any help you can provide on this subject :)
I am not familiar with the specific DLL in question, but it sounds like you did not register the DLL on the target machine. You can do this by running regsvr32.exe or by calling the DLL's exported DllRegisterServer function or by using side-by-side assemblies. You need to do register the DLL on each machine that needs to leverage the COM functionality within it, so when you distribute your application, make sure that your installer registers the DLL if you go the regsvr32.exe route.
You can use the #import directive in Microsoft Visual C++ to load the information contained within the DLL without using a header file or rewriting it yourself based on documentation.

ActiveX component can't create an object

I am getting error,
ActiveX component can't create object.
Actually I have VB6 DLLs where business logic resides and I am calling that DLL function in my VB.NET application, all DLLs are dependent on other DLLs. I am getting the error from one of the DLLs
Any ideas?
Usually that error points to a COM dll that is not registered. You need to look at the chain of calls and find out which COM components you need and make sure they are available. Process Monitor (from sysinternals) may help you find it when it reads from the registry and can't find it.
Four common causes are:
1. You do not have a required TLB or ActiveX DLL/OCX file
2. A TLB or ActiveX DLL/OCX needed by the project is present but not registered on your system
3. The VB runtimes are an earlier version than the one you need to run the project
4. A required TLB or ActiveX DLL/OCX file is corrupt
Do you have access to the troublesome DLL source code?
Also check permissions. The user account that the vb.net application is running under will need permissions to be able to create the vb6 dll
Process Monitor will definately help find the missing DLL, but frequently the task can be achieved more quickly with Dependency Walker.