1. 程式人生 > >COM在登錄檔中的相關鍵值及其意義(這個很詳細,必須轉)

COM在登錄檔中的相關鍵值及其意義(這個很詳細,必須轉)

轉自 http://www.cnblogs.com/developersupport/archive/2013/06/02/COM-registry.html

COM在登錄檔中的相關鍵值及其意義

概要

當編寫好一個COM並將其在系統中註冊之後,這些登錄檔項到底位於Register中的什麼位置,系統是如何通過這些登錄檔項在Runtime時候找到某個COM的,這些都是診斷COM相關的問題至關重要的資訊。總的來說,系統是通過GUID來查詢每個物件的,比如TypeLib,Interface和Class都有其相應的GUID(16bytes的字串)。本文介紹了一個COM在註冊後,系統登錄檔會被寫入哪些鍵值,以及這些鍵值所代表的意義。

正文

COM是一種基於獨立於開發語言的程式設計模型。因此在描述COM功能和介面的時候採用了與程式語言無關的介面描述語言(IDL)來編寫介面的抽象定義,該介面定義檔案(*.IDL)經過Platform SDK自帶的Microsoft IDL編譯器編譯之後將生成相應的標頭檔案、型別庫等。
如下是一個簡單的型別庫定義檔案(OOPCOM.idl)

複製程式碼

// OOPCOM.idl : IDL source for OOPCOM.dll
// This file will be processed by the MIDL tool to
// produce the type library (OOPCOM.tlb) and marshalling code. 
import "oaidl.idl";
import "ocidl.idl";
       [
              object,
              uuid(DB20D9BF-FAA4-4D23-9243-19860EB4482A),
              dual,
              helpstring("ISimpleClass Interface"),
              pointer_default(unique)
       ]
       interface ISimpleClass : IDispatch
       {
              [id(1), helpstring("method HelloWorld")] HRESULT HelloWorld([out,retval]BSTR *result);
       };
 
[
       uuid(FE0FAA57-2E27-425F-9FA3-518E73F729FB),
       version(1.0),
       helpstring("OOPCOM 1.0 Type Library")
]
library OOPCOMLib
{
       importlib("stdole32.tlb");
       importlib("stdole2.tlb");
 
       [
              uuid(1CF4A019-A754-44F1-B164-047A3F0AC184),
              helpstring("SimpleClass Class")
       ]
       coclass SimpleClass
       {
              [default] interface ISimpleClass;
       };    
}; 

複製程式碼

本文主要介紹以下幾個COM相關常見概念:

 

  1. COM Interface
  2. COM Class
  3. Type Library
  4. Application ID &Name

 

COM的相關表項在登錄檔中的位置及其意義:

表項一:COM Interface 
登錄檔路徑 : HKEY_CLASSES_ROOT\Interface\[X] 或者:HKLM\Software\Classes\Interface\[x]

在以上的OOPCOM.idl,我們看到其Inferface ID (IID)為DB20D9BF-FAA4-4D23-9243-19860EB4482A,其在Register中的位置如圖所示。

在COM的Interface表項中包含

  1. ProxyStubClsid :該鍵值的具體內容請參考下圖。
  2. ProxyStubClsid32 :該鍵值的具體內容參考下圖。該鍵值與ProxyStubClsid相同值。
  3. TypeLib: 與該interface相關的COM 型別庫定義。

在Interface中,有關ProxyStubClsid和ProxyStubClsid32所指向的CLSID值如下圖所示:

ProxyStubClsid鍵值和ProxyStubClsid32起什麼作用呢?這需要對COM client和COM service是如何進行通訊和資料交換的有所瞭解。
當COM client和COM Server application不在同一個程序地址空間時,COM會建立一個客戶端的proxy和server端的stub。例如當client呼叫CoCreateInstance()時,在伺服器將介面指標返回給COM之後,COM將介面指標返回給client之前,COM為指定的介面建立proxy和stub並將指向proxy的指標返回給client。我們把類似這樣的過程叫做Marshaling (彙集)。
開發人員可以實現IMarshal這個interface來支援自定義的Marshaling。而如果物件不支援自定義Marshaling,則COM使用proxy和stub程式執行標準Marshaling,因此COM必須從登錄檔中獲得提供proxy和stub程式生成器的DLL的CLSID。這就是我們為什麼ProxyStubClsid(32)的意義所在。
如果開發的COM支援自動化技術,即實現了IDispatch interface(支援解釋型語言的呼叫,如vbscript等),則其Marshaling的DLL一般為以上所示的oleaut32.dll (16bit系統則為ole2disp.dll)。如果其不支援該技術,則其Marshaling的DLL一般為ole32.dll

表項二:COM Class
登錄檔路徑: HKEY_CLASSES_ROOT\CLSID\[X] 或者:HKLM\Software\Classes\CLSID\[x]

預設情況下,在CLSID下面包含以下鍵值(如上圖所示)

  1. LocalServer32
  2. ProgID
  3. TypeLib
  4. Programmable (omitted)


LocalServer32: 
該鍵用來指定執行在程序外的COM Server Application的.EXE檔案path。與之相似的一個表項是:InprocServer32。COM執行模式有2種,一種為程序內模式,即COM與Client在同一個程序記憶體之內,執行在這種模式下的COM必須只能為*.DLL,指定其具體COM module的path的時候,即用InprocServer32來指定;另外一種是Out of Process(OOP),即Client和COM Server Application位於不同的Process地址空間,而這種COM必須為*.EXE,指定其具體COM module 的path時候,即用LocalServer32來指定。
而這兩種模式下的COM呼叫過程也不盡相同。
1.伺服器為*.DLL時,呼叫過程如下所示:

2. 當伺服器為*.EXE 時,其過程如下所示:

ProgID:
實際上ProgID和CLSID都是一回事,只不過是2種不同的叫法而已,ProgID可以說是CLSID的nickname吧。相對於CLSID一串16bytes的難以記憶的數字, ProgID顯得更為人性化,系統提供了相應API: GetClsIdFromProgid(t_ProgID) 可以實現ProgID和CLSID之間的互換。
TypeLib:
不用多講了, 該鍵在COM interface鍵中也出現過,用來指定該COM的型別庫檔案。
既然在COM Interface和COM class中都出現了Type Library,那就看看TypeLib 鍵吧。

表項三: COM Type Library
登錄檔路徑: HKEY_CLASSES_ROOT\TypeLib\ [X]

TypeLib的各項鍵值如上圖所示。
還有一項不太注意的Register Entry就是AppID。當把COM註冊到系統之後,系統會在 HK_ROOT\AppID 下面生成一個指向該COM的AppID Entry。預設情況下,會使用COM module name作為該Application name,從而使得該COM/DCOM 可讀。如下圖5在dcomcnfg.exe中所示,該AppID和一個readable的Application Name對應起來。

表項四:COM Application相關注冊表項
登錄檔路徑: HKEY_CLASSES_ROOT\AppID\[X]

 

希望以上內容對您有所幫助

Winston He