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”在哪里?

换句话说,我正在寻找文档。

4

7 回答 7

14

到目前为止我所知道的。COM 基于它的clsid创建一个对象。这是一个唯一标识该类的指南。

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 服务器对象支持的线程模型。本例中使用的最简单、最常见的一种是“Apartment”线程模型:

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 有了 clasid,它就可以在下面的注册表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 具有定义所有类方法的类型库,它会自动为您执行此操作。

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

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 文章指出,您必须添加一个虚拟可编程键以表明它是一个 ActiveX 控件:

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

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

但这并不能阻止一些 ActiveX 使用 Control,一些使用 Programmable,还有一些两者都使用。

我找不到任何提到其他需要的东西。

那么,任何人都可以找到一些权威的文档吗?

于 2008-11-12T19:33:05.237 回答
5

拉里奥斯特曼提供了一个很好的起点:

这种“货物崇拜”性质的很大一部分是这样一个事实,即可以为 COM 对象设置一组令人眼花缭乱的注册表设置,如果有的话,尚不清楚哪个适用。因此,我试图列出一系列文章,以帮助人们确定他们需要设置的内容。

--注册 COM 对象需要哪些注册表项。

摘要:这取决于您需要在哪些场景中使用您的对象。最基本、绝对必要的设置是默认值和 ThreadingModel HKEY_CLASSES_ROOT\CLSID\<clsid>\,但大多数时候您还需要 ProgID 和 AppID。

于 2008-11-12T17:07:15.203 回答
5

查找/借用/窃取 Kraig Brockenschmidt 的 Inside OLE 2 副本。它像世界一样古老(也和我约会:-))

这也是上述注册表项的高级概述。

阅读 Larry Osterman 的博客文章以获取更多指导。

查看MSDN ActiveX示例。

此外,您在 HKCR\Interfaces 下缺少控件实现的所有自定义接口和事件接口的条目。

于 2008-11-12T17:12:58.997 回答
3

它并不详尽,但请尝试这篇MS 知识库文章。

此外,Larry Osterman在这里有一篇有用的博文。


我想到另一种方法是使用RegMon之类的工具,并在调用 DllRegisterServer 方法时直接监视所做的注册表更改。

于 2008-11-12T17:09:12.640 回答
0

无论如何,请使用链接的 Larry Osterman 文章。

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

于 2008-11-12T17:10:26.957 回答
0

旁注,如果您想通过实验查看创建了哪些键:使用 Sysinternals 的Process Monitor,它会在您注册控件时实时捕获注册表上的活动。

于 2008-11-12T17:58:49.200 回答
-1

您在使用 64 位操作系统吗?

如果是这样,而不是写入
HKEY_CLASSES_ROOT\CLSID\
您应该写入
HKEY_CLASSES_ROOT\Wow6432Node\CLSID\

于 2013-03-19T12:39:52.690 回答