在 SQL Server 進程外部執行 DLL 型 COM 物件
本文說明如何在 SQL Server 進程之外執行 DLL 型 COM 物件。
原始產品版本:SQL Server
原始 KB 編號: 198891
摘要
Microsoft SQL Server 提供透過一組 OLE 自動化預存程式或透過擴充預存程式載入及執行自定義元件物件模型 (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) 的預設設定,這表示在進程內部或外部執行物件。 您必須將 參數變更為四 (4),這表示此元件要以本機可執行檔的形式執行。 使用類似下列範例的語法,以明確通知 DCOM 使用sp_OACreate
預存程式從進程外執行 COM 物件:DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
如果在擴充預存程式中建立 COM 物件,則可以將 的第
CoCreateInstanceEx
三個 參數CoCreateInstance
變更為CLSCTX_LOCAL_SERVER
。 這會顯示在下列程式代碼範例中使用CoCreateInstance
:HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
修改登錄以強制遠端處理物件
如果您無法修改 COM 用戶端以要求物件已從進程外建立,則存在兩個不同的方法,以強制對象脫離進程。
使用隨附於 Visual C++ 的 OLE/COM 物件查看器 (oleview.exe),並在 [所有物件] 底下尋找 ProgID
OLEComponent.Object
。 選取 COM 物件,然後從 [物件 ] 功能選取CoCreateInstance
[旗標]。 請確定只CLSCTX_LOCAL_SERVER
選取 。 接下來,在 [實作] 和 [Inproc 伺服器] 索引卷標底下,選取 [使用代理程式],並將 [自定義代理路徑] 保留空白,讓載入dllhost.exe檔案,並將 COM DLL 帶入其進程空間中。使用下列步驟手動更新登錄。
警告
如果您使用登錄編輯程式或其他方法修改登錄時不正確,就可能發生嚴重的問題。 可能需要重新安裝作業系統才能解決這些問題。 Microsoft 不保證可以解決這些問題。 Modify the registry at your own risk.
取得 COM 物件的類別識別碼 (CLSID)。 CLSID 是 128 位的數位,並視為全域唯一標識碼 (GUID),用來唯一識別包含此 COM 物件的元件、模組或檔案。 使用 OLE Automation 預存程式建立 COM 物件時,預存程式的第一個參數是程式設計標識符,或是使用 OLE 物件的 ProgID 來衍生 CLSID。 此字元字串描述 OLE 物件的類別,並且具有下列格式:
OLEComponent.Object
您可以使用程式設計識別碼來尋找 COM 物件的類別識別碼。
開啟註冊表編輯器 (regedit.exe),並在機碼下
HKEY_CLASSES_ROOT
使用Find
方法來尋找具有 OLEComponent.Object> 名稱的<機碼。 您會在其他層級找到它,但它應該位於 之下的HKEY_CLASSES_ROOT
層級。 找到金鑰之後,請展開金鑰名稱的資料夾,您應該會看到名為CLSID的子機碼。 選取該資料夾以查看該索引鍵內的值。 畫面右側是名為 Default 的標題。 該索引鍵的數據格式應如下:{59F929A0-74D8-11D2-8CBC-08005A390B09}
記下此值,或將它複製到 [記事本]。 包含括弧。
流覽至
HKEY_CLASSES_ROOT\CLSID
機碼底下,並尋找具有此 GUID 號碼的子機碼。 反白顯示HKEY_CLASSES_ROOT\CLSID
機碼之後,您可以在註冊表編輯器中使用 [尋找] 函式 (在 [編輯 ] 功能表下),並將 GUID 貼到 [尋找 ] 對話框中。 檢查此機碼底下的 InprocServer32 子機碼,以指向 COM DLL 檔案的位置,確定您已找到適當的介面。 如果有 TypeLib 機碼,請檢查此 GUID 值。 這應該與您在步驟 1 中所指出的內容不同。 否則,您有 TypeLib GUID,而不是 COM 物件的 GUID。 ProgID 子機碼的值OLEComponent.Object.1
會是 。 最後一個只針對這個範例,並用於版本控制資訊。雖然在 GUID 的 InprocServer32 子機碼下,請確定
ThreadingModel
值存在,而且它已設定為 [兩者] 或 [免費],以確保封送處理會瞭解 COM 物件的線程模型,以在 SQL Server 進程空間外執行 COM。ThreadingModel
如果沒有值或設定為 Apartment,COM 物件具現化可能不一致。注意
如果您新增
ThreadingModel
值,請務必先測試 COM 物件,再實作。反白顯示金鑰底下的
HKEY_CLASSES_ROOT\CLSID
GUID 數位/子機碼。 從 [ 編輯] 功能表中,選取 [ 新增],然後選取 [ 字串值]。 在 [名稱] 資料行底下,輸入 AppID。按 ENTER 鍵,然後插入您從步驟 1 指出的類別識別碼或 GUID 號碼作為值。 GUID 應該位於大括弧內,如下列範例所示:
{59F929A0-74D8-11D2-8CBC-08005A390B09}
DCOM 會使用應用程式識別碼 AppID 將 DLL 與可執行檔產生關聯。
在下
HKEY_CLASSES_ROOT\AppID
新增子機碼,並將其名稱設定為與上一個步驟中插入的括號相同的類別標識碼或 GUID 編號。反白顯示 GUID 名稱。 從 [ 編輯] 功能表中,選取 [ 新增],然後選取 [ 字串值]。 在 [名稱] 數據行底下,輸入 dllSurrogate。
將這個值的數據行保留空白。 因為數據行是空白的,這會通知 DCOM 執行預設可執行檔、 dllhost.exe,並在其進程空間中載入 COM 物件。
關閉 [登錄編輯程式]。 按兩下 [ 開始],然後選取 [ 執行]。 在 [ 執行 ] 對話框中,輸入 DCOMCNFG。
按 ENTER 鍵以開啟 [分散式 COM 組態屬性] 對話框。 按兩下 [ 預設屬性] 索引標籤,並確定 已選取 [在此電腦上啟用分散式 COM ]。 如果不是,請選取它,然後選取 [ 套用]。
請確定執行 SQL Server 的 Windows NT 使用者帳戶具有 此物件的登錄機碼的完整控制 許可權。 如果許可權不足或登錄機碼輸入不正確,當您建立 COM 物件時,可能會發生下列錯誤:
OLE Automation 錯誤資訊
HRESULT:0x80040154
來源:ODSOLE 擴充程式
描述:類別未註冊OLE Automation 錯誤資訊
HRESULT: 0x80070005
來源:ODSOLE 擴充程式
描述:拒絕存取。OLE Automation 錯誤資訊
HRESULT:0x80080005
來源:ODSOLE 擴充程式
描述:伺服器執行失敗測試並查看這是否正在執行 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 進程空間之外建立的。 使用 tlist.exe 的快照集是在 COM 物件存在於dllhost.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