首页
学习
活动
专区
圈层
工具
发布

COM简介
EN

Stack Overflow用户
提问于 2014-04-19 09:54:44
回答 4查看 594关注 0票数 1

我刚开始读大学的时候,Java和.NET是用于教学的技术。

在过去的三年中,我已经熟悉了COM (Component )等基于组件对象模型(Component)的语言,并获得了经验。我理解基于COM的语言和高层次的现代语言之间的区别。

我不明白登记处发生了什么事。例如,我执行以下命令:

代码语言:javascript
复制
regsvr32 myDLL.dll

然后,我可以在: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID下面找到一个条目。这是为VB6程序创建的唯一条目吗?例如,如果我这样做了,那么DLL仍然可用吗?

  1. 正确注册DLL:regsvr32 myDLL.dll
  2. 导出注册表项: HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\
  3. 正确注销DLL:regsvr32 -u myDLL.dll
  4. 导入步骤2中导出的注册表项。

我试过了,但没有用。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-04-20 10:17:04

Regsvr32.exe是一个非常的简单程序,它对注册本身贡献很少。它只使用LoadLibrary()加载您作为参数传递的DLL,然后使用GetProcAddress()在DLL中定位导出的函数。这就是DllRegisterServer(),如果您使用/u选项注销注册,那么它将查找DllUnregisterServer()。然后调用函数,仅此而已。

DllRegisterServer是由组件作者编写的。它所做的一切都是不可预测的,任何事情都是可能的。但是当然也有共性,它的目的是编写组件需要从另一个程序中使用的注册表项。您需要使用SysInternals的进程监视器,它的跟踪准确地显示了正在执行的操作。

您已经知道了HKLM\Software\Classes\CLSID\{guid}注册表项。非常重要的是,这就是驱动客户端程序中的CoCreateInstance()调用的原因。它通过简单地指定一个数字( CLSID)在服务器中创建一个对象,COM基础结构确保正确的DLL被定位和加载,它的DllGetClassObject()入口点是提供对象的工厂函数。

核心特性是客户端程序不需要知道任何关于DLL本身的信息,它所做的就是提供一个数字,然后神奇地得到一个创建的对象。它为DLL的构造提供了很大的灵活性,完全不依赖于编写DLL源代码的语言。例如,在编写ComVisible .NET组件时,C#这样的语言不支持导出像DllGetClassObject()这样的函数。仍然工作(有点超出范围),客户端完全忽略了使其工作的CLR中的管道。

几乎任何COM服务器的注册函数都会写入以下键:

  • HKLM\Classes\Software\CLSID\{guid}\InprocServer32。为服务器实现的每个coclass编写。此键的默认值包含DLL的路径。告诉COM管道要加载哪个DLL以找到DllGetClassObject入口点。进程外服务器( EXE而不是DLL)使用LocalServer32键.
  • ThreadingModel值在CLSID中。指定COM对象的线程要求。非常常见的是“套间”,它告诉COM基础设施,COM对象不是线程安全的,而COM应该以线程安全的方式调用服务器内部的函数。其他公共值有“两种”( .NET组件的默认值)和“免费”,它们是为能够自行处理工作线程调用的组件编写的。
  • HKLM\Classes\Software\Interface\{guid}\ProxyStubClsid32。为COM coclass实现的每个接口编写。任何非空闲线程的COM对象都需要,它包含一个COM对象的CLSID,该对象知道如何将接口方法上的调用从一个线程封送到另一个线程。您发现的一个非常常见的值是{00020424-0000-0000-C000-000000000046},这是Windows中包含的默认封送程序,它知道如何根据类型库的内容封送调用。自定义服务器也并不少见,特别是对于通过描述IDL语言中的接口启动的COM服务器。这种组件的代理/存根可以从IDL自动生成。
  • HKLM\Classes\Software\Interface\{guid}\Typelib。对于依赖标准封送处理程序的服务器,默认值是类型库的guid。
  • HKLM\Classes\Software\Typelib\{guid}。对于依赖标准封送处理程序的服务器,将告诉COM在哪里找到它需要的类型库。
  • HLKM\Classes\Software\{progid}。对于支持后期绑定的服务器来说,这是非常常见的,允许从脚本语言(如Javascript或VBScript )中使用它们。其中{progid}是一个友好的字符串,用于标识组件而不是guid。支持以多种语言表示的CreateObject()运行时支持函数。这个键中的CLSID子键告诉运行时它应该使用哪个guid来定位CLSID键。

您可能会看到更多的键正在写入。ActiveX组件在CLSID中写入一串键以将信息传递给主机应用程序和编程工具(如VB6 )。用.NET编写的服务器添加了几个键,以帮助CLR定位包含ComVisible组件的程序集。

票数 10
EN

Stack Overflow用户

发布于 2014-04-19 14:57:15

然后我可以在以下找到一个条目:HKEY-本地机器-CLSID.这是为VB6程序创建的唯一条目吗?

不,有多项;例如,\TYPELIBSOFTWARE\CLASSES\PROGID,其中PROGIDYourSever.YourClass标识符。

当您注销您的组件时,这些内容将被删除,因此重新使用CLSID键将不会恢复功能。

如果类型定义没有存储在文件中(在它们注册之前),那么它们是否被存储?

COM DLL可以将其类型库内部存储为二进制TYPELIB资源。

票数 2
EN

Stack Overflow用户

发布于 2014-04-19 15:00:19

记住,regsvr32不是魔法。它加载目标DLL (或OCX)并调用该库的自注册入口点。这通常会产生一个或多个类( ProgIds )和类型库的基本注册,每当VB6编译器生成一个类时,这些类和类型库就嵌入到这样的DLL中。ActiveX EXE以类似的方式执行自注册,但不通过外部调用方执行.相反,将完成EXE的特殊运行,传递regserver命令行开关。

自我注册不是在目标系统上安装这些东西的首选方法。它只是编译器可以生成的最基本的注册核心,而不需要读取开发人员的想法。它还完全跳过在注册表中创建重要的服务条目,例如卸载程序链接、创建/递增使用计数等等。它不能产生大量的其他注册表项,代码可能依赖这些条目(shell扩展信息、数据文件类型/扩展名关联、服务信息、DCOM激活参数等)。

其他编译器提供在单独的类型文件中创建类型信息的选项,但VB6没有。

所以你的建议是合理的,但遗漏了很多东西。首先,您省略了在HKEY_CLASSES_ROOT\TypeLib\下找到的类型信息(typelib)注册,但是在HKEY_CLASSES_ROOT\下也有ProgId信息,等等。

有关更多信息,请参见INFO:由ActiveX组件创建的注册表项

记住,VB6不是创建原始COM组件,而是创建ActiveX组件,这是一个COM添加OLE2方面的超集。

.Net依赖于基于文件位置的更原始的类似Java的机制,除非您的GAC程序集(注册表发布的.Net版本)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23168542

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档