共用方式為


在 SQL Server 進程外部執行以 DLL 為基礎的 COM 物件

本文說明如何在 SQL Server 進程之外執行以 DLL 為基礎的 COM 物件。

原始產品版本: SQL S
原始 KB 編號: 198891

摘要

Microsoft SQL Server 提供透過一組 OLE Automation 預存程式或透過擴充預存程式, (COM) 物件載入和執行自定義元件物件模型的功能。 根據預設,以 DLL 為基礎的 COM 物件會在進程伺服器中載入,這表示 COM 物件不僅會載入 SQL Server 進程記憶體位址空間內,還具有此記憶體位址空間的完整存取權。 因此,載入 SQL Server 進程空間中的 COM 物件必須遵守與任何 DLL 檔案相同的規則。 COM 物件可能會覆寫 SQL Server 進程內的記憶體或流失資源,導致不穩定。

如果懷疑 COM 物件可能會影響 SQL Server 程式的健全性,您可能會想要使用本文中的步驟,在 SQL Server 進程空間之外具現化 COM 物件。 在操作系統中實作分散式元件物件模型的 (DCOM) 位置透明度規格,讓您能夠在 SQL Server 進程空間之外執行以 DLL 為基礎的 COM 物件。

在主要應用程式的位址空間之外執行 DLL 型 COM 物件的程式稱為遠端處理。 遠端處理需要另一個可執行檔做為代理程式,以取代 SQL Server 可執行檔。 DCOM 服務控制管理員 (rpcss.exe) 使用的預設可執行檔案 dllhost.exe命名為 。 DCOM 支援結構會使用 dllhost.exe 檔案將 DLL 載入其處理空間,然後使用 Proxy/存根配對,以透明方式將要求的介面封送處理回用戶端,在此案例中是 SQL Server。 此可執行檔可以同時接受多個介面/方法要求。 介面使用完成之後,DCOM 服務控制管理員 (SCM) 管理 dllhost.exe 檔案的清理和卸除。 不應預期 COM 物件會在具現化之間保留狀態資訊。

下列步驟可以套用至正在 SQL Server 進程空間中建立的任何 DLL 型 COM 對象,不論是透過 或擴充預存程式具現化sp_OACreate

其他相關資訊

您可以用來具現化進程外 COM 物件之兩個基本方法的相關信息如下。

COM 用戶端要求遠端物件

藉由變更叫用 COM 物件的方式,您可以要求在 SQL Server 位址空間之外建立物件。

  • 如果 COM 物件是使用 sp_OACreate 程式載入,預設會在進程中載入。 不過,這個程式有選擇性的第三個參數,您可以使用這個參數來指出要在何處建立對象的內容。 如果未指定此參數,則會使用預設設定 5 (5) ,這表示在進程內部或外部執行物件。 您必須將 參數變更為四 (4) ,這會向 DCOM 指出此元件是以本機可執行檔執行。 使用類似下列範例的語法,明確通知 DCOM 使用sp_OACreate預存程式在進程外執行 COM 物件:

    DECLARE @object int
    DECLARE @hr int
    EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
    
  • 如果 COM 物件是在擴充預存程式內建立,則 或 的第三個參數CoCreateInstanceCoCreateInstanceEx可以變更為 CLSCTX_LOCAL_SERVER。 這會在下列程式代碼範例中使用 CoCreateInstance顯示:

    HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER,
    IID_IUnknown, (void**)&piunknown);
    

修改登錄以強制遠端處理物件

如果您無法修改 COM 用戶端以要求在進程外建立物件,則存在兩種不同的方法,以強制在進程外建立物件。

  • 使用隨附於 Visual C++ 的 OLE/COM 物件查看器 (oleview.exe) ,然後在 OLEComponent.Object [ 所有物件] 底下尋找 ProgID。 選取 COM 物件,然後從 [ 物件 ] 功能選取 [ CoCreateInstance 旗標]。 請確定只 CLSCTX_LOCAL_SERVER 選取 。 接下來,在 [ 作和 Inproc 伺服器] 索引標籤下,選取 [ 使用 Surrogate 進程 ],並將 [自定義 Surrogate 的路徑 ] 保留空白,以允許載入 dllhost.exe 檔案,並將 COM DLL 帶入其進程空間內。

  • 使用下列步驟手動更新登錄。

    警告

    Serious problems might occur if you modify the registry incorrectly by using Registry Editor or by using another method. 可能需要重新安裝作業系統才能解決這些問題。 Microsoft 不保證可以解決這些問題。 Modify the registry at your own risk.

    1. 取得 COM 物件的類別標識碼 (CLSID) 。 CLSID 是128位的數位,並視為全域唯一標識碼 (GUID) ,用來唯一識別包含此 COM物件的元件、模組或檔案。 使用 OLE Automation 預存程式建立 COM 物件時,預存程式的第一個參數是程式設計標識符,或是使用 OLE 物件的 ProgID 來衍生 CLSID。 此字元字串描述 OLE 物件的類別,並具有下列格式:

      OLEComponent.Object
      
    2. 您可以使用程式設計識別碼來尋找 COM 物件的類別識別碼。

      開啟登錄 編輯器 (regedit.exe) ,並在機碼下HKEY_CLASSES_ROOT使用 Find 方法來尋找具有 OLEComponent.Object> 名稱的<密鑰。 您會在其他層級找到它,但它應該位於 直接在 下的層級。HKEY_CLASSES_ROOT 找到金鑰之後,展開金鑰名稱的資料夾,您應該會看到名為CLSID的子機碼。 選取該資料夾以查看該索引鍵內的值。 畫面右側是名為 Default 的標題。 該索引鍵的數據應為下列格式:

      {59F929A0-74D8-11D2-8CBC-08005A390B09}

      記下此值,或將它複製到記事本。 包含方括弧。

    3. 在機碼下巡覽 HKEY_CLASSES_ROOT\CLSID ,並尋找具有此 GUID 編號的子機碼。 反白HKEY_CLASSES_ROOT\CLSID顯示機碼之後,您可以使用 [編輯] 功能表下方的 [登錄] 編輯器 (中的 [尋找] 函式) 並將 GUID 貼到 [尋找] 對話框中。 檢查此索引鍵下的 InprocServer32 子機碼,確定您已找到適當的介面,其指向 COM DLL 檔案的位置。 如果有 TypeLib 金鑰,請檢查此 GUID 值。 這應該與您在步驟 1 中記下的不同。 否則,您會有 TypeLib GUID,而不是 COM 物件的 GUID。 ProgID 子機碼的值 OLEComponent.Object.1為 。 最後一個僅適用於此範例,並用於版本控制資訊。

    4. 在 GUID 的 InprocServer32 子機碼下,請確定ThreadingModel某個值存在,並將其設定為 Both 或 Free,以確保封送處理瞭解 COM 物件的線程模型,以在 SQL Server 進程空間中執行 COM。 ThreadingModel如果沒有值或設定為 Apartment,COM 物件具現化可能不一致。

      注意事項

      如果您新增 ThreadingModel 值,請確定您在實作之前測試了 COM 物件。

    5. 在索引鍵下 HKEY_CLASSES_ROOT\CLSID 反白顯示 GUID 編號/子機碼。 從 [ 編輯] 功能表中,選取 [ 新增],然後選取 [ 字串值]。 在 [ 名稱] 資料 行下,輸入 AppID

    6. ENTER 鍵,然後插入您從步驟 1 記下的類別識別碼或 GUID 編號作為值。 GUID 應該位於大括弧內,如下列範例所示:

      {59F929A0-74D8-11D2-8CBC-08005A390B09}
      

      DCOM 會使用應用程式識別碼 AppID 來建立 DLL 與可執行檔的關聯。

    7. 在下新增子機碼, HKEY_CLASSES_ROOT\AppID 並將其名稱設定為與上一個步驟中插入的括號相同的類別標識碼或 GUID 編號。

    8. 反白顯示 GUID 名稱。 從 [ 編輯] 功能表中,選取 [ 新增],然後選取 [ 字串值]。 在 [ 名稱] 數據 行下,輸入 dllSurrogate

      將此值的 [資料] 資料行保留空白。 因為數據行是空白的,所以這會通知 DCOM 執行預設的可執行檔 、dllhost.exe,並在其進程空間內載入 COM 物件。

    9. 關閉 [登錄編輯程式]。 按兩下 [開始],然後選取 [ 執行]。 在 [ 執行] 對話框中,輸入 DCOMCNFG

      ENTER 鍵以開啟 [分散式 COM 組態屬性 ] 對話框。 按兩下 [ 預設屬性] 索引標籤,並確定已選取 [在此電腦上 啟用分散式 COM ]。 如果不是,請選取它,然後選取 [ 套用]

    10. 請確定 SQL Server 執行的 Windows NT 用戶帳戶具有此物件登錄機碼的 [完全控制] 許可權。 如果許可權不足或登錄機碼輸入不正確,當您建立 COM 物件時,可能會發生下列錯誤:

      OLE Automation 錯誤資訊
      HRESULT:0x80040154
      來源:ODSOLE 擴充程式
      描述:類別未註冊

      OLE Automation 錯誤資訊
      HRESULT: 0x80070005
      來源:ODSOLE 擴充程式
      描述:拒絕存取。

      OLE Automation 錯誤資訊
      HRESULT:0x80080005
      來源:ODSOLE 擴充程式
      描述:伺服器執行失敗

    11. 測試並查看這是否正在執行 dllhost.exe 檔案,並在其進程空間中載入 COM 物件。 這需要 Windows NT 資源套件位於 SQL Server 執行所在的 Windows NT 計算機上。 開啟命令提示字元,然後從命令提示字元執行 tlist.exe 檔案,其中顯示所有進程及其相關聯的進程標識碼,或 (PID) 的進程標識碼。 在執行 的 Transact-SQL 腳本 sp_OACreate 中,以及執行該呼叫之後,但在腳本結束之前,請使用下列命令將腳本完成延遲 20 秒:

      WAITFOR DELAY '000:00:20'
      

      執行文稿,並立即流覽至命令提示字元,並執行 tlist.exe 檔案。 記下 dllhost.exe PID。 重新執行 tlist.exe 並傳遞 PID 作為參數。 這會顯示在dllhost.exe進程空間內載入 DLL。 以 DLL 為基礎的 COM 物件應該列為在此進程中執行。 腳本傳回之後,再次執行 tlist.exe 會顯示 dllhost.exe 進程已不再執行。

      在下列範例輸出中,為 ADODB。 連接物件會建立在 SQL Server 進程空間之外。 當 COM 物件存在於 dllhost.exe 進程空間中時,會執行這個使用 tlist.exe 的快照集。 請注意,會載入模組 msado15.dll,也就是包含 COM 物件的模組。

      C:\>tlist dllhost
      275 dllhost.exe
      CWD: C:\NT40\system32\
      CmdLine: C:\NT40\System32\dllhost.exe {00000514-0000-0010-8000-00AA006D2EA4}
      -Embedding
      VirtualSize: 19180 KB PeakVirtualSize: 19180 KB WorkingSetSize: 1780 KB
      PeakWorkingSetSize: 1780 KB
      NumberOfThreads: 3
      278 Win32StartAddr:0x01001920 LastErr:0x00000000 State:Waiting
      215 Win32StartAddr:0x00001b5e LastErr:0x00000000 State:Waiting
      253 Win32StartAddr:0x00001b60 LastErr:0x000000cb State:Waiting
      4.0.1381.105 shp 0x01000000 dllhost.exe
      4.0.1381.130 shp 0x77f60000 ntdll.dll
      4.0.1381.121 shp 0x77dc0000 ADVAPI32.dll
      4.0.1381.133 shp 0x77f00000 KERNEL32.dll
      4.0.1381.133 shp 0x77e70000 USER32.dll
      4.0.1381.115 shp 0x77ed0000 GDI32.dll
      4.0.1381.131 shp 0x77e10000 RPCRT4.dll
      4.0.1381.117 shp 0x77b20000 ole32.dll
        6.0.8267.0 shp 0x78000000 MSVCRT.dll
                       0x1f310000 msado15.dll
       2.30.4265.1 shp 0x766f0000 OLEAUT32.dll
       4.0.1381.72 shp 0x77bf0000 rpcltc1.dll
      

參考資料

Transact-SQL) (OLE Automation 預存程式