1 STA套间

当线程被创建后,用COM库初始化就建立起一个STA套间, 有两种初始化方法

  • CoInitialize(NULL);
  • CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);

在线程结束之前,调用CoUninitialize结束套间

COM在套间线程中创建了一个隐藏的窗口, 套间线程包含消息循环, 用于同步, 分发消息

  • 在STA中创建的COM对象都属于这个STA
  • STA对象不必处理同步,因为对象的方法代码只能被这个STA套间的线程调用

image.png
所有的com调用, 都被序列化到 创建对象的那个线程 内去执行,而不一定在你的调用线程执行

关于 proxy(代理) 和 stub(存根)

  • Stub 跟 Proxy 是一对,俗称“代理-桩”,一般用在远程方法调用
  • Proxy 相当于是拿在手里的遥控器,而 Stub 相当于电视里的遥控接收器
  • Proxy 的接口供客户端程序调用,然后它内部会把信息包装好,以某种方式(比如 RMI)传递给 Stub,而后者通过对应的接口作用于服务端系统,从而完成了“远程调用”

2 MTA套间

每个进程至多只有一个MTA套间, 其中可以包含多个线程, 有一种初始化方法

  • CoInitializeEx(NULL, COINIT_MULTITHREADED);

MTA套间中的对象必须thread-safe

  • 被MTA中线程创建的对象为MTA对象, 它们并没有生存在任何特定的线程中,
  • MTA中的线程都可以直接访问MTA对象

image.png
RPC (Remote Procedure Call),即“远程过程调用”
所有的com调用, 都在你的调用线程执行, 所以mta的调用效率是最高的

3 对于大漠插件

在插件设计的所有接口,
对于同个对象而言,不是多线程安全的(也就是同个对象的接口,不能同时在多个线程内调用,会引发崩溃)
如果不是同个对象,那么是多线程安全的.
所以当脚本中有检测线程和执行线程时, 要么创建两个大漠对象来应付这两个线程, 要么使用互斥锁

大漠免注册
首先解释一下,不注册调用大漠插件,实际上是使用dmreg.dll来配合实现,这个文件有2个导出接口
SetDllPathW和SetDllPathA。 SetDllPathW对应unicode,SetDllPathA对应ascii接口.
参数如下
SetDllPathA 字符串(Ascii码表示插件所在的路径),整数(0表示STA,1表示MTA)
SetDllPathW 字符串(Unicode码表示插件所在的路径),整数(0表示STA,1表示MTA)
那么这2个函数就可以代替以往我们使用的 regsvr32注册方式,或者RegDll注册方式。