Search code examples
windowsactivexdllregistration

What are the alternatives to dll registration for ActiveX


An application I have recently started work on has to register two dll's, "because of ActiveX".

This makes it difficult to have multiple version of the application present on your machine - say the installed product version, and Debug and Release versions of the latest development sources.

What are the alternatives to registration for ActiveX.


Solution

  • If your application loads the ActiveX objects, there are a couple of options. The first option if you are using XP or newer, it to use a Registration-Free COM with a Manifest file as explained on MSDN. The idea is to declare your COM (ActiveX) components in a manifest file instead of the registry. So for MyApp.exe, create MyApp.exe.manifest with the following (using your DLL file name and CLSID):

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
      <assemblyIdentity type="win32" name="MyApp_ActiveX" version="1.0.0.1" 
            processorArchitecture="x86" publicKeyToken="0000000000000000" />
    
      <file name="MyActiveX.dll">
        <comClass clsid="{0000000-0000-0000-0000-000000000000}" threadingModel="Both" />
      </file>
    </assembly>
    

    The other option as DougN mentioned is to roll your own CoCreateInstance() to create the object. The following C++ (plus ATL) code should do it (going from memory so double check the code):

    typedef int (__stdcall *LPDLLGETCLASSOBJECT)(REFCLSID, REFIID, void**);
    
    // LoadInterface() - Load COM Interface from DLL without using registry.
    //
    // USAGE:   
    //   HMODULE hModule = 0;
    //   CComPtr<IMyActiveX> pActiveX;
    //   if(SUCCEEDED(LoadInterface("C:\\Debug\\MyActiveX.dll", CLSID_MyActiveX, IID_IMyActiveX, (void**)&pActiveX, &hModule)))
    //   {
    //      // TODO: use pActiveX
    // 
    //      // caller must call FreeLibrary(hModule) when done
    //      pActiveX = 0;
    //      FreeLibrary(hModule); 
    //   }
    //
    HRESULT LoadInterface(LPCTSTR pDllPath, REFCLSID rClsid, REFIID riid, LPVOID* ppv, HMODULE *pModule)
    {
        if(pModule == 0 || ppv == 0) return E_POINTER;
        HMODULE hModule = LoadLibrary(pDllPath);
        if(hModule == 0) return E_FAIL;
    
        HREUSLT hr = E_POINTER;
        CComPtr<IClassFactory> classFactory;
        LPDLLGETCLASSOBJECT pGetClassObject = (LPDLLGETCLASSOBJECT)GetProcAddress(hModule, "DllGetClassObject");
        if(pGetClassObject)
        {
            hr = pGetClassObject(rClsid, IID_IClassFactory, (void**)&classFactory);
            if(SUCCEEDED(hr))
            {
                hr = classFactory->CreateInstance(0, riid, (void**)ppv);
                if(SUCCEEDED(hr))
                {
                    *pModule = hModule;
                    return S_OK;
                }
            }
        }
    
        // unload library on error
        if(hModule)  
        {
            FreeLibrary(hModule);
        }
        return hr;
     }