2

我最近开始工作的一个应用程序必须注册两个 dll,“因为 ActiveX”。

这使得在您的机器上存在多个版本的应用程序变得很困难 - 例如已安装的产品版本,以及最新开发源的调试和发布版本。

ActiveX 注册的替代方法是什么。

4

5 回答 5

3

如果您的应用程序加载 ActiveX 对象,则有几个选项。如果您使用的是 XP 或更新版本,则第一个选项是使用带有 Manifest 文件的免注册 COM,如MSDN上所述。这个想法是在清单文件而不是注册表中声明您的 COM (ActiveX) 组件。因此,对于 MyApp.exe,使用以下内容创建 MyApp.exe.manifest(使用您的 DLL 文件名和 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>

DougN 提到的另一个选项是滚动您自己的 CoCreateInstance() 来创建对象。下面的 C++(加上 ATL)代码应该这样做(从内存中去,所以仔细检查代码):

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;
 }
于 2009-05-02T04:00:23.507 回答
0

没有我能想到的。这就是 COM(因此是 ActiveX)背后的全部原理。

于 2009-05-01T14:11:00.690 回答
0

如果您控制加载 ActiveX 控件的代码,并且没有其他人需要加载它,您可以跳过注册并手动处理您自己的 CreateInstance 调用:LoadLibrary,获取指向 Factory 对象的指针,然后直接创建实例。

大约 10 年前在一个项目上做过,效果很好。

但是,如果您不能这样做(也许您不控制调用 CreateInstance 的代码),那么只需创建两个批处理文件并将它们放在您的桌面上:一个用于注册 Debug,另一个用于注册 Release DLL。然后来回切换变得非常容易。

于 2009-05-01T14:15:55.827 回答
0

您可以使用ProgID对 ActiveX 控件进行版本控制。

于 2009-05-01T18:39:01.373 回答
0

我不认为 .bat 解决方案一定很糟糕。大多数简单的 ActiveX 控件都是自注册/注销的。但它仍然限制您一次运行调试版本或发布版本,而不是同时运行两者。

这是一个大问题(它是“DLL Hell”的本质),也是.NET 和Java 流行的很大一部分原因。

我相信 .NET 可以利用并行共享,这是 Windows 2000 和 Windows 98 SE 引入的一项功能。我不认为你需要 .NET 来使用它(你没有说你在做 COM 互操作)。

在http://msdn.microsoft.com/en-us/library/ms811700.aspx上的 MSDN 上有一篇有点长的文章,“在应用程序中实现并行组件共享”,它建议创建一个 .local 文件。我不完全清楚它是如何工作的,但我认为这是正确的方法。

于 2009-05-06T01:27:47.003 回答