DLL ベースの COM オブジェクトをプロセス外でSQL Serverする

この記事では、DLL ベースの COM オブジェクトをプロセス外で実行するSQL Serverします。

元の製品バージョン:  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 オブジェクトをインスタンス化することができます。 オペレーティング システムへの Location Transparency の分散コンポーネント オブジェクト モデル (DCOM) 仕様の実装により、SQL Server プロセス領域の外側で DLL ベースの COM オブジェクトを実行する機能が提供されています。

メイン アプリケーションのアドレス空間外で DLL ベースの COM オブジェクトを実行するプロセスは、リモート処理と呼ばれる。 リモート処理では、別の実行可能ファイルが、別の実行可能ファイルの代SQL Server必要です。 DCOM Service Control Manager (Rpcss.exe) で使用される既定Dllhost.exe。 DCOM サポート構造では、Dllhost.exe ファイルを使用して DLL をプロセス空間に読み込み、プロキシ/スタブペアを使用して要求されたインターフェイスをクライアントに透過的にマーシャリングします(この場合は SQL Server)。 この実行可能ファイルは、複数のインターフェイス/メソッド要求を同時に受け入れできます。 インターフェイスの使用が完了すると、DCOM Service Control Manager (SCM) は、ユーザー ファイルのクリーンアップとアンロードをDllhost.exeします。 COM オブジェクトは、インスタンス化の間に状態情報を保持する必要があります。

次の手順は、SQL Server プロセス空間で作成される DLL ベースの COM オブジェクトに適用できます。インスタンス化中か拡張ストアド プロシージャか。  sp_OACreate

詳細情報

COM オブジェクトをプロセス外にインスタンス化するために使用できる 2 つの基本的なメソッドに関する情報は次のとおりです。

COM クライアントがオブジェクトのリモート処理を要求する

COM オブジェクトの呼び出し方法を変更することで、オブジェクトをアドレス空間の外部に作成SQL Serverできます。

  • プロシージャを使用して COM オブジェクトが読み込 sp_OACreate まれる場合、既定ではプロセスに読み込まれます。 ただし、この手順にはオプションの 3 番目のパラメーターがあります。このパラメーターを使用して、オブジェクトを作成する場所のコンテキストを示す場合があります。 このパラメーターを指定しない場合は、既定の 5 (5) の設定が使用されます。つまり、プロセスの内部または外部でオブジェクトを実行します。 パラメーターを 4 (4) に変更する必要があります。これは、このコンポーネントをローカル実行可能ファイルとして実行する DCOM に示します。 次の例に似た構文を使用して、ストアド プロシージャを使用して COM オブジェクトをプロセスから実行する DCOM に明示的sp_OACreate 通知します。

    DECLARE @object int
    DECLARE @hr int
    EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
    
  • COM オブジェクトが拡張ストアド プロシージャ内に作成されている場合は、3 番目のパラメーターまたは CoCreateInstance CoCreateInstanceEx に変更できます CLSCTX_LOCAL_SERVER 。 これは、次のコード サンプルで次の使用例を使用して示されています CoCreateInstance

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

オブジェクトのリモート処理を強制するためにレジストリを変更する

COM クライアントを変更してオブジェクトの作成をプロセス外に要求できない場合は、2 つの異なるメソッドが存在して、オブジェクトを強制的にプロセス外に作成します。

  • OLE/COM オブジェクト ビューアー (Oleview.exe) を使用して、Visual C++ で [すべてのオブジェクト] の形式で ProgID OLEComponent.Object を探します。 COM オブジェクトを選択し、[オブジェクト] メニューから [フラグ] を CoCreateInstance 選択します。 選択されているの CLSCTX_LOCAL_SERVER は必ず確認してください。 次に、[実装] タブと [Inproc Server] タブの下で [代理プロセスの使用] を選択し、[カスタム サロゲートへのパス] を空白のままにして、Dllhost.exe ファイルを読み込み、COM DLL をプロセス領域内に持ち込む必要があります。

  • レジストリを手動で更新するには、次の手順を使用します。

    警告

    レジストリ エディターまたは別の方法を使用してレジストリを誤って編集すると、深刻な問題が発生することがあります。 このような問題が発生した場合は、オペレーティング システムの再インストールが必要になることがあります。 こうした問題の修復について、マイクロソフトはいかなる保証もいたしません。 レジストリの変更はユーザー自身の責任において行ってください。

    1. COM オブジェクトのクラス識別子 (CLSID) を取得します。 CLSID は 128 ビットの数値で、この COM オブジェクトを含むコンポーネント、モジュール、またはファイルを一意に識別するために使用されるグローバル一意識別子 (GUID) と見なされます。 OLE オートメーション ストアド プロシージャを使用して COM オブジェクトを作成する場合、ストアド プロシージャの最初のパラメーターはプログラム識別子か、OLE オブジェクトの ProgID を使用して CLSID を派生します。 この文字列は、OLE オブジェクトのクラスを表し、次の形式です。

      OLEComponent.Object
      
    2. プログラム識別子を使用して、COM オブジェクトのクラス識別子を検索できます。

      レジストリ エディター (Regedit.exe) を開き、キーの下でメソッドを使用して HKEY_CLASSES_ROOT 、oleComponent.Object ファイルの名前を持つ<を検索 Find>。 他のレベルで見つけることができますが、直接下のレベルに位置する必要があります HKEY_CLASSES_ROOT 。 キーを見つけると、キー名のフォルダーを展開すると、CLSID という名前のサブキーが表示されます。 そのフォルダーをクリックすると、そのキー内の値が表示されます。 画面の右側には、(Default) という名前のタイトルがあります。 そのキーのデータは、次の形式である必要があります。

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

      この値をメモするか、この値をコピーしてメモ帳。 角かっこを含める。

    3. キーの下を HKEY_CLASSES_ROOT\CLSID 移動し、この GUID 番号のサブキーを見つけます。 キーを強調表示した後、レジストリ エディター ([編集] メニューの下) で [検索] 関数を使用し、[検索] ダイアログ ボックスに GUID を HKEY_CLASSES_ROOT\CLSID 貼り付けます。 COM DLL ファイルの場所を示す、このキーの下にある InprocServer32 サブキーを調べることです。 TypeLib キーがある場合は、この GUID 値を確認します。 これは、手順 1 で示した方法とは異なる必要があります。 それ以外の場合は、COM オブジェクトの GUID ではなく TypeLib GUID を使用します。 ProgID サブキーの値は 'OLEComponent.Object.1' になります。 最後の 1 つは、このサンプル専用であり、バージョン管理情報に使用されます。

    4. GUID の InprocServer32 サブキーの下で、値が存在し、マーシャリングが com オブジェクトのスレッド モデルを理解し、SQL Server プロセス領域から COM の実行を有効にすることを確認するために、値が [両方] または [無料] に設定されている必要があります。 ThreadingModel 値が指定されていないか、または Apartment に設定されている場合 ThreadingModel 、COM オブジェクトのインスタンス化が一貫性を保てない可能性があります。

      注意

      値を追加する ThreadingModel 場合は、実装する前に COM オブジェクトをテストしてください。

    5. キーの下にある GUID 番号/サブキーを強調表示 HKEY_CLASSES_ROOT\CLSID します。 [編集] メニューの [新規] をクリックし、[文字列値] を選択します。 [名前] 列の下に、AppID と入力します。

    6. Enter キーを押し、手順 1 で指定したクラス識別子または GUID 番号を値として挿入します。 GUID は、次の例のように中かっこ内にある必要があります。

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

      アプリケーション識別子 AppID は、DCOM が DLL を実行可能ファイルに関連付ける場合に使用します。

    7. の下に新しいサブキーを追加し、前の手順で挿入したかっこで囲まれた同じクラス識別子または GUID 番号に名前 HKEY_CLASSES_ROOT\AppID を設定します。

    8. GUID 名を強調表示します。 [編集] メニューの [新規] を クリックし、[文字列値] を選択します。 [名前 ] 列に*「DllSurrogate」と入力します*。

      この値については、[データ] 列を空白のままにします。 データ列は空白なので、DCOM に既定の実行可能ファイルを実行し、Dllhost.exeを実行し、そのプロセス領域内で COM オブジェクトを読み込む必要があります。

    9. レジストリ エディタを閉じます。 [スタート] ボタンをクリックし、[ファイル名を指定して実行] をクリックします。 [実行 ] ダイアログ ボックスで 、「DCOMCNFG」と入力します

      ENTER キー を押 して、[分散 COM 構成 のプロパティ] ダイアログ ボックス を開きます。 [既定の プロパティ] タブ をクリックし、このコンピューターで 分散 COM を有効にするが選択されている必要があります。 選択されていない場合は、それを選択し、[適用] を クリックします

    10. 実行中のユーザー Windows NTアカウントSQL Server、このオブジェクトのレジストリ キーに対するフルコントロールアクセス許可を持っている必要があります。 アクセス許可が十分でないか、レジストリ キーが正しく入力されていない場合、COM オブジェクトを作成するときに次のエラーが発生する可能性があります。

      OLE オートメーション エラー情報
      HRESULT: 0x80040154
      ソース: ODSOLE 拡張プロシージャ
      説明: クラスが登録されていません

      OLE オートメーション エラー情報
      HRESULT: 0x80070005
      ソース: ODSOLE 拡張プロシージャ
      説明: アクセスが拒否されました。

      OLE オートメーション エラー情報
      HRESULT: 0x80080005
      ソース: ODSOLE 拡張プロシージャ
      説明: サーバーの実行に失敗しました

    11. このファイルを実行して、COM オブジェクトDllhost.exeプロセス空間に読み込むのをテストして確認します。 これには、リソース キットWindows NTが実行されているWindows NTコンピューター SQL Server必要があります。 コマンド プロンプトを開き、コマンド プロンプトから Tlist.exe ファイルを実行します。このファイルには、すべてのプロセスと関連付けられたプロセス識別子、またはプロセス識別子 (PID) が表示されます。 Transact-SQL スクリプトで実行され、その呼び出しが実行された後で、スクリプトが終了する前に、次のコマンドを使用して、スクリプトの完了を sp_OACreate 20 秒間延期します。

      WAITFOR DELAY '000:00:20'
      

      スクリプトを実行し、すぐにコマンド プロンプトに移動し、コマンド ファイルTlist.exeします。 PID のDllhost.exe注意してください。 再実行Tlist.exe PID をパラメーターとして渡します。 これは、プロセス領域内に読み込まれる dll をDllhost.exeします。 DLL ベースの COM オブジェクトは、このプロセス内で実行されているとして一覧表示する必要があります。 スクリプトが戻った後、Tlist.exe実行すると、Dllhost.exeが実行されなくなりました。

      次の出力例では、ADODB を指定します。 接続オブジェクトは、プロセス領域の外部SQL Server作成されます。 このスナップショットは、Tlist.exe領域に COM オブジェクトが存在している間Dllhost.exe実行されました。 COM オブジェクトをMsado15.dllモジュールであるモジュールが読み込まれるのに注意してください。

      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
      

関連情報

OLE オートメーション ストアド プロシージャ (Transact-SQL)