Win32:注册ActiveX控件所需的注册表条目?

11
我需要编写当调用DllRegisterServer时运行的代码,即当有人调用以下代码时:
regsvr32 myActiveX.ocx

我试图查找所需注册表条目的明确列表(而不仅仅是通过在注册表中搜索来汇集的内容)。

到目前为止,我的探险发现了以下内容:

HKEY_CLASSES_ROOT
   \MyCoolLibrary.MyCoolControl
      \Clsid
         (default) = "{myClassId}"
   \CLSID
      \{myClassId}
         \Control
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \MiscStatus
            \1
               (default) = 205201
         \ProgID
            (default) = "MyCoolLibrary.MyCoolControl"
         \ToolboxBitmap32
            (default) = "c:\foo\myActiveX.ocx,1"
         \TypeLib
            (default) = "{myTypeLibraryGuid}"
         \Verb
            \0
               (default) = "Properties,0,2"
         \Version
            (default) = "1.0"
   \TypeLib
      \{myTypeLibraryGuid}
         \1.0
            (default) = "MyCoolLibrary.MyCoolControl"

现在,有一些问题需要解决: - 控件文件夹包含什么?它的存在是否表示控件? - 205201的MiscStatus是什么?205202会有什么不同? - 动词“Properties,0,2”是什么意思?“Properties,0,0”和“Properties,0,1”在哪里?
换句话说,我正在寻找文档。

1
我是一名COM开发人员,一个新手。我有相同的问题。我想与您分享这个 - smwikipedia
大多数框架不是都自动为你生成了吗? - Deanna
7个回答

14

据我所知,COM基于其clsid创建对象。这是一个唯一标识该类的GUID。

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}

然后使用该类创建对象。COM现在需要知道保存该COM对象的DLL的位置。在我这个特定的案例中,展示COM对象的“服务器”是一个DLL,并且将是“进程内”的。我们通过添加以下内容来将COM指向该“进程内”dll:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"

COM还需要了解COM服务器对象支持的线程模型。最简单、最常见且在此示例中使用的是“单元”线程模型:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"

接下来是ProgID。这类似于DNS将友好的名称转换为IP地址的方式。在这里,我们将友好的名称"MyCoolLibrary.MyCoolControl"转换成丑陋的clsid"{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

现在有人可以请求

MyCoolLibrary.MyCoolControl

COM可以将其转换为ClassID。

{AE8530CF-D204-4877-9CAB-F052BF1F661F}

一旦 COM 获得了 classid,它就可以在注册表中查找 HKCR\Clsid\{AE8530CF-D204-4877-9CAB-F052BF1F661F} 下的实际信息。

为了好玩,ProgID 添加到 Clsid 部分,这样人们就可以对这个类有一些想法:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

接下来是类型库。对于任何进程内的内容,这基本上不重要,但如果COM对象在另一个“公寓”中,那么函数参数需要进行封送处理。如果有一个定义了所有类方法的类型库,COM会自动为您执行此操作。

通过添加TypeLib键,clsid部分将指向适当的类型库:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
         \TypeLib            
             (default) = "{17A5A3D4-439C-4C2A-8AB4-749B7771CDE1}"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"

这个类型库的信息也存储在注册表中,但通过调用RegisterTypeLib来为我们添加这些键。但它会为我们添加类似于以下的键:

HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \InprocServer32
            (default) = "c:\foo\myActiveX.ocx"
            ThreadingModel = "Apartment"
         \ProgID
             (default) = "MyCoolLibrary.MyCoolControl"
         \TypeLib            
             (default) = "{17A5A3D4-439C-4C2A-8AB4-749B7771CDE1}"
HKEY_CLASSES_ROOT
    \MyCoolLibrary.MyCoolControl
       \Clsid
           (default) = "{AE8530CF-D204-4877-9CAB-F052BF1F661F}"
HKEY_CLASSES_ROOT
    \TypeLib
        \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
           \1.0
              (default) = "My Cool ActiveX Library"
           ...

现在我们进入棘手的部分,这些是让一个ActiveX控件有望工作所需的东西。

一篇MSDN文章指出,您必须添加一个虚假的Programmable键来表示它是一个ActiveX控件:


HKEY_CLASSES_ROOT
   \Clsid
      \{AE8530CF-D204-4877-9CAB-F052BF1F661F}
         \Programmable

然而,这个MSDN Library页面说关键字是Control,而不是Programmable,且没有Programmable关键字。

但是这并不妨碍一些ActiveX使用Control,有些使用Programmable,还有一些同时使用两者。

我找不到任何提到需要其他任何内容的信息。

因此,有人能找到一些明确的文档吗?


1
“可编程”似乎是正确的关键字 - 我无法使用“控件”加载MSOffice中的组件,而没有“可编程”。此外,我建议将版本号附加到“ProgID”(MyCoolLibrary.MyCoolControl.1),并保留一个不附加版本号的“VersionIndependentProgID”。 - alecov

5
Larry Osterman提供了一个很好的起点:
“这种‘货柜崇拜’的一大部分原因是有一系列令人困惑的注册表设置可以用于COM对象,而且不清楚哪些设置适用。因此,我试图撰写一系列文章,以帮助人们确定他们需要设置什么。”
-- 需要哪些注册表项来注册COM对象。 总结:它取决于您需要在哪些情况下使用对象。最基本、绝对必要的设置是HKEY_CLASSES_ROOT\CLSID\<clsid>\中的默认值和线程模型,但大多数时候您也需要ProgIDs和AppIDs。

5

找/借/偷一本Kraig Brockenschmidt的《Inside OLE 2》。这本书很老(也揭示了我的年龄 :-))

这里还有一个高级概述提到的注册表条目。

阅读Larry Osterman的博客文章,获取更多指针。

查看MSDN ActiveX样例。

此外,您需要为控件实现的所有自定义接口和事件接口在HKCR\Interfaces下添加条目。


3
这里有一篇微软知识库文章(链接),虽然不是详尽无遗的,但可以试试。
此外,Larry Osterman的博客(链接)也很有用。
还有一个方法是使用像RegMon这样的工具,直接监视调用DllRegisterServer方法时所做的注册表更改。

0

无论如何,可以参考链接的Larry Osterman文章。

此外,一个很好的起点是由MSVC ATL COM对象向导生成的ATL注册表脚本。您可以尝试不同的选项并查看它们如何影响输出。


0
如果你想实验性地查看创建的键,可以使用Sysinternals的Process Monitor,它会在你注册控件时即时捕获注册表上的活动。

-1
你正在使用64位操作系统吗?
如果是的话,你应该将写入路径从HKEY_CLASSES_ROOT\CLSID\更改为HKEY_CLASSES_ROOT\Wow6432Node\CLSID\。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接