dspace-group/dscom

combase error - class not registered

Closed this issue · 10 comments

This may be an error on my part, but I thought I'd bring it up here in case there's a bug to fix, or even a clarification that can be made on the main page. Consistently when I run my CPP code, that imports a tlb and attempts to point to a class, I'm getting this error:
onecore\com\combase\dcomrem\resolver.cxx(2299)\combase.dll!77A61A49: (caller: 77ADABBC) ReturnHr(1) tid(3a1c) 80040154 Class not registered

The error occurs when I call "PSP_CSLibraryDLLClassPtr p(__uuidof(PSP_CSLibrary));" - I'm guessing that it's PSP_CSLibrary which is the unregistered class.

Note that this error does not appear if I use an old tlb made with tlbexp.exe
I already made sure the tlb was created with --win32 (from AnyCpu), which matched my C++ architecture, and then I registered it with "dscom tlbregister".
Is there anything more I have to do? Register the dll somehow? Do something extra to register the class? The class itself has a unique GUID in my C# file as well. Not sure what to do, or where this error is coming from.

Hi Delucion,

please try the dscom32.exe.
You can download it here: https://github.com/dspace-group/dscom/releases

And try the following:

  1. dscom32.exe tlbexport <your.dll> # This must create sysKind: SYS_WIN32

  2. From an admin console dscom32.exe tlbregister <your.tlb>

  3. Check with dscom32.exe tlbdump <your.tlb> -o <your-output.yaml> if the TLB created with tlbexp.exe is identical with the tlb created with dscom.
    The GUID of the TypeLib (TypeLibId) should be different - this is okay

  4. Is in both cases the sysKind: SYS_WIN32 ?

  5. Check if the TypeLibId is present in the windows registry.

  6. Check if the GUID __uuidof(PSP_CSLibrary is the correct one.

For step 3, there are a number of discrepancies, even though they have the same architecture. These are the attributes that were different: (under attributes of an interface) alignment, size, virtualMemoryTableSize, (elsewhere) vTableOffset. For each of them, the one made with the original dscom with the --win32 flag had values that were twice that of those in the dscom32.exe version - probably something to be fixed.

Also the GUID of the type library was not different anywhere, and in many parts of the code that GUID was all 0's (not everywhere though - it seems like certain classes received a GUID with numbers, though also it was mostly 0's and always the same one)

  1. Yes, it was SYS_WIN32 in both

  2. The TypeLibGuid that had numbers, mentioned earlier showed up under HKEY_CLASSES_ROOT\Interface\ . Now if you meant the first guid in the file (attribute of the file?), the one that is referenced by the interfaces (which I guess to links them back to the type library), that is under HKEY_CLASSES_ROOT\TypeLib\ as well as HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\ (should they be in both places? the first one might be from an old version of the file I didn't unregister, since from what I understand 32 bit tlbs are registered in WOW6432Node)

  3. How do I check this? It throws the "class not found" error as it tries to find the uuidof, using the text name of the class. When the code breaks, could I find the GUID with visual studio somehow? I just feel like I won't be able to, since the whole point of the line is to get the guid

Update to 6: I was able to find the GUID of the class, and it did match what was in the TLB file for it. I used StringFromCLSID(__uuidof(PSP_CSLibrary), &lpolestr); (from a microsoft example) - and this did NOT throw an error. So there's something going on when I try to make a pointer with "PSP_CSLibraryDLLClassPtr p(__uuidof(PSP_CSLibrary));"

Hi the StringFromCLSID just remaps a GUID to a string and is not using the registry where the COM information is stored. To check if the class is registered you should use ProgIdFromCLSID. If this call succeeds the class is registered.

        LPOLESTR lpolestrProgId = NULL;
        HRESULT hr = ProgIDFromCLSID(__uuidof(PSP_CSLibrary), &lpolestrProgId);
        if (SUCCEEDED(hr))
        {
            CoTaskMemFree(lpolestrProgId);
        }
        else
        {
              // Class not registered
        }

If not, register your class as shown in the MSDN

In fact there is a problem with the "--win32" switch.
I had to remove the feature.
If you want to create a 32Bit TLB, then you have to download the dscom32.exe from the release page.

There is now a sample application that shows how dscom32.exe works with a 32 bit application.
https://github.com/dspace-group/dscom/tree/main/examples/32bit

Your problem with "Class not registered" could be this one:
dotnet/runtime#32493

This means that you can create a 32 bit TLB with dscom32.exe from an AnyCPU assembly, but you have to register a 32 bit assembly with regserv32.exe.
So better don't use AnyCPU.

I have also changed dscom documentation:
https://github.com/dspace-group/dscom#32bit-support

Success!!! It seems there were a few things I was getting wrong on my end:
I had been so caught up in that making tlb's wouldn't work with .NET 6 that I neglected the fact I needed to register the comhost.dll - I had been wondering about this because normally regsvr32 works with the dll, with the tlb being optional. I had looked into trying it a few times, but I got an error. Turns out, I was transferring the comhost dll without all the other necessary files, like the .pdb and runtimeconfig.json - things not specified by the MSFT documentation as necessary! I also assume that the x86 aspect for the C# project made a difference, given the linked issue from the dotnet project.

That said, your demo really helped to solidify the necessary process. I will say though that despite following it and it technically working, it did print out the "CreateInstance failure" message.

When I saw everything go through, my jaw dropped! Thank you Mark and Sschukat for helping me through with this obscure issue, and I'm glad I could give some feedback for the project here as well!!

I'm glad to hear that!

You can close this issue if you like.
Good luck with your migration project and thanks for your feedback.