Ausführen eines DLL-basierten COM-Objekts außerhalb des SQL Server-Prozesses

In diesem Artikel wird beschrieben, wie Sie ein DLL-basiertes COM-Objekt außerhalb des SQL Server-Prozesses ausführen.

Ursprüngliche Produktversion: SQL Server
Ursprüngliche KB-Nummer: 198891

Zusammenfassung

Microsoft SQL Server bietet die Möglichkeit, benutzerdefinierte COM-Objekte (Component Object Model) über eine Reihe gespeicherter OLE-Automatisierungsprozeduren oder erweiterte gespeicherte Prozeduren zu laden und auszuführen. Dll-basierte COM-Objekte werden standardmäßig als auf dem Prozessserver geladen, was bedeutet, dass die COM-Objekte nicht nur innerhalb des SQL Server Prozessspeicheradressraums geladen werden, sondern auch Vollzugriff auf diesen Speicheradressraum haben. Daher muss ein com-Objekt, das in den SQL Server Prozessbereich geladen wird, dieselben Regeln wie jede DLL-Datei einhalten. Es besteht die Möglichkeit, dass ein COM-Objekt den Speicher innerhalb des SQL Server Prozesses überschreibt oder Ressourcen kompromittiert, was zu Instabilität führt.

Wenn der Verdacht besteht, dass ein COM-Objekt die Stabilität des SQL Server Prozesses beeinträchtigen könnte, sollten Sie die Schritte in diesem Artikel verwenden, um das COM-Objekt außerhalb des SQL Server Prozessbereichs zu instanziieren. Die Implementierung der DCOM-Spezifikation (Distributed Component Object Model) von Location Transparency in das Betriebssystem bietet die Möglichkeit, ein DLL-basiertes COM-Objekt außerhalb des SQL Server Prozessbereichs auszuführen.

Das Ausführen eines DLL-basierten COM-Objekts außerhalb des Adressraums der Standard Anwendung wird als Remoting bezeichnet. Remoting erfordert, dass eine andere ausführbare Datei ein Ersatzprozess anstelle der SQL Server ausführbaren Datei ist. Die vom DCOM-Dienststeuerungs-Manager (rpcss.exe) verwendete ausführbare Standarddatei heißt dllhost.exe. Die DCOM-Unterstützungsstruktur verwendet die dllhost.exe-Datei, um die DLL in ihren Prozessbereich zu laden, und verwendet dann Proxy-Stub-Paare, um die angeforderte Schnittstelle transparent zurück an den Client zu marshallen, was in diesem Fall die SQL Server ist. Diese ausführbare Datei kann mehrere Schnittstellen-/Methodenanforderungen gleichzeitig akzeptieren. Nach Abschluss der Verwendung der Schnittstelle verwaltet der DCOM Service Control Manager (SCM) die Bereinigung und das Entladen der dllhost.exe-Datei . COM-Objekte sollten keine Zustandsinformationen zwischen Instanziierungen beibehalten.

Die folgenden Schritte können für jedes DLL-basierte COM-Objekt gelten, das im SQL Server Prozessbereich erstellt wird, unabhängig davon, ob es über sp_OACreate oder eine erweiterte gespeicherte Prozedur instanziiert wird.

Weitere Informationen

Es folgen Informationen zu den beiden grundlegenden Methoden, die Sie verwenden können, um das COM-Objekt außerhalb des Prozesses zu instanziieren.

COM-Client fordert Remoting des Objekts an

Indem Sie die Art und Weise ändern, wie Sie das COM-Objekt aufrufen, können Sie anfordern, dass das Objekt außerhalb des SQL Server Adressraums erstellt wird.

  • Wenn das COM-Objekt mithilfe der sp_OACreate -Prozedur geladen wird, wird es standardmäßig im Prozess geladen. Es gibt jedoch einen optionalen dritten Parameter für diese Prozedur, mit dem Sie den Kontext angeben können, in dem das Objekt erstellt werden soll. Wenn dieser Parameter nicht angegeben wird, wird die Standardeinstellung von fünf (5) verwendet, was bedeutet, dass das Objekt innerhalb oder außerhalb des Prozesses ausgeführt wird. Sie müssen den Parameter in vier (4) ändern, was DCOM angibt, dass diese Komponente als lokale ausführbare Datei ausgeführt werden soll. Verwenden Sie eine Syntax, die dem folgenden Beispiel ähnelt, um DCOM explizit zu informieren, das COM-Objekt mithilfe der sp_OACreategespeicherten Prozedur außerhalb des Prozesses auszuführen:

    DECLARE @object int
    DECLARE @hr int
    EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
    
  • Wenn das COM-Objekt in einer erweiterten gespeicherten Prozedur erstellt wird, kann der dritte Parameter von CoCreateInstance oder CoCreateInstanceEx in CLSCTX_LOCAL_SERVERgeändert werden. Dies wird im folgenden Codebeispiel mit CoCreateInstancegezeigt:

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

Ändern der Registrierung, um Remoting des Objekts zu erzwingen

Wenn Sie den COM-Client nicht ändern können, um anzufordern, dass das Objekt aus dem Prozess erstellt wird, gibt es zwei verschiedene Methoden, um zu erzwingen, dass das Objekt außerhalb des Prozesses erstellt wird.

  • Verwenden Sie den OLE/COM-Objekt-Viewer (oleview.exe), der im Lieferumfang von Visual C++ enthalten ist, und suchen Sie die ProgID im Format unter OLEComponent.ObjectAlle Objekte. Wählen Sie das COM-Objekt und dann im Menü Objekt die Option Flags aus CoCreateInstance . Stellen Sie sicher, dass nur CLSCTX_LOCAL_SERVER ausgewählt ist. Wählen Sie als Nächstes auf den Registerkarten Implementierung und Inproc Server die Option Surrogatprozess verwenden aus, und lassen Sie den Pfad zum benutzerdefinierten Ersatzzeichen leer. Dadurch kann die dllhost.exe Datei geladen und die COM-DLL in ihren Prozessbereich eingefügt werden.

  • Führen Sie die folgenden Schritte aus, um die Registrierung manuell zu aktualisieren.

    Warnung

    Schwerwiegende Probleme können auftreten, wenn die Registrierung mit dem Registrierungs-Editor oder einer anderen Methode unsachgemäß bearbeitet wird. Diese Probleme können eine Neuinstallation des Betriebssystems erforderlich machen. Microsoft kann nicht garantieren, dass diese Probleme behoben werden können. Das Ändern der Registrierung erfolgt auf eigenes Risiko.

    1. Rufen Sie den Klassenbezeichner (CLSID) des COM-Objekts ab. Die CLSID ist eine 128-Bit-Zahl und gilt als GUID (Globally Unique Identifier), die verwendet wird, um die Komponente, das Modul oder die Datei, die dieses COM-Objekt enthält, eindeutig zu identifizieren. Beim Erstellen von COM-Objekten mithilfe der gespeicherten Prozeduren der OLE-Automatisierung ist der erste Parameter für die gespeicherte Prozedur ein programmgesteuerter Bezeichner, oder die ProgID des OLE-Objekts wird verwendet, um die CLSID abzuleiten. Diese Zeichenfolge beschreibt die Klasse des OLE-Objekts und hat die folgende Form:

      OLEComponent.Object
      
    2. Sie können den programmgesteuerten Bezeichner verwenden, um den Klassenbezeichner für ein COM-Objekt zu suchen.

      Öffnen Sie die Registrierungs-Editor (regedit.exe), und verwenden Sie unter dem HKEY_CLASSES_ROOT Schlüssel die Find -Methode, um einen Schlüssel mit dem Namen Ihres <OLEComponent.Object> zu suchen. Sie finden sie auf anderen Ebenen, aber sie sollte sich auf der Ebene direkt unter befinden HKEY_CLASSES_ROOT. Nachdem Sie den Schlüssel gefunden haben, erweitern Sie den Ordner für den Schlüsselnamen. Daraufhin sollte ein Unterschlüssel mit dem Namen CLSID angezeigt werden. Wählen Sie diesen Ordner aus, um die Werte in diesem Schlüssel anzuzeigen. Auf der rechten Seite des Bildschirms befindet sich ein Titel mit dem Namen Standard. Die Daten für diesen Schlüssel sollten in der folgenden Form vorliegen:

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

      Notieren Sie sich diesen Wert, oder kopieren Sie ihn in Editor. Schließen Sie die Klammern ein.

    3. Navigieren Sie unter dem HKEY_CLASSES_ROOT\CLSID Schlüssel, und suchen Sie den Unterschlüssel mit dieser GUID-Nummer. Nachdem Sie den HKEY_CLASSES_ROOT\CLSID Schlüssel hervorgehoben haben, können Sie die Funktion Suchen im Registrierungs-Editor (im Menü Bearbeiten) verwenden und die GUID in das Dialogfeld Suchen einfügen. Stellen Sie sicher, dass Sie die richtige Schnittstelle gefunden haben, indem Sie den Unterschlüssel InprocServer32 unter diesem Schlüssel überprüfen, der auf den Speicherort Ihrer COM-DLL-Datei verweist. Wenn ein TypeLib-Schlüssel vorhanden ist, überprüfen Sie diesen GUID-Wert. Dies sollte sich von dem unterscheiden, was Sie in Schritt 1 notiert haben. Andernfalls verfügen Sie über die TypeLib-GUID und nicht über die GUID für das COM-Objekt. Der ProgID-Unterschlüssel hat den Wert OLEComponent.Object.1. Die am Ende ist nur für dieses Beispiel und wird für Versionsverwaltungsinformationen verwendet.

    4. Stellen Sie unter dem Unterschlüssel InprocServer32 der GUID sicher, dass ein ThreadingModel Wert vorhanden ist und entweder auf Both oder Free festgelegt ist, um sicherzustellen, dass das Marshalling das Threadingmodell des COM-Objekts versteht, um die Ausführung von COM aus SQL Server Prozessbereich zu ermöglichen. Wenn kein ThreadingModel Wert vorhanden ist oder auf Apartment festgelegt ist, ist die COM-Objektinstanziierung möglicherweise nicht konsistent.

      Hinweis

      Wenn Sie den ThreadingModel Wert hinzufügen, stellen Sie sicher, dass Sie ihr COM-Objekt vor der Implementierung testen.

    5. Markieren Sie die GUID-Nummer/den Unterschlüssel unter dem HKEY_CLASSES_ROOT\CLSID Schlüssel. Wählen Sie im Menü Bearbeiten die Option Neu und dann Zeichenfolgenwert aus. Geben Sie in der Spalte Name den Namen AppID ein.

    6. Drücken Sie die EINGABETASTE , und fügen Sie dann den Klassenbezeichner oder die GUID-Nummer ein, die Sie sich aus Schritt 1 als Wert notiert haben. Die GUID sollte sich wie im folgenden Beispiel in den geschweiften Klammern befinden:

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

      Der Anwendungsbezeichner AppID wird von DCOM verwendet, um die DLL einer ausführbaren Datei zuzuordnen.

    7. Fügen Sie einen neuen Unterschlüssel unter dem HKEY_CLASSES_ROOT\AppID hinzu, und legen Sie den Namen auf den gleichen Klassenbezeichner oder die gleiche GUID-Nummer mit den Klammern fest, die im vorherigen Schritt eingefügt wurden.

    8. Markieren Sie den GUID-Namen. Wählen Sie im Menü Bearbeiten die Option Neu und dann Zeichenfolgenwert aus. Geben Sie in der Spalte Name den Namen dllSurrogate ein.

      Lassen Sie die Spalte Daten für diesen Wert leer. Da die Datenspalte leer ist, wird DCOM dadurch informiert, die ausführbare Standarddatei dllhost.exeauszuführen und das COM-Objekt innerhalb des Prozessbereichs zu laden.

    9. Schließen Sie den Registrierungs-Editor. Klicken Sie auf Start, und wählen Sie dann Ausführen aus. Geben Sie im Dialogfeld Ausführen den Namen DCOMCNFG ein.

      Drücken Sie die EINGABETASTE , um das Dialogfeld Eigenschaften der verteilten COM-Konfiguration zu öffnen. Klicken Sie auf die Registerkarte Standardeigenschaften , und stellen Sie sicher, dass Verteiltes COM auf diesem Computer aktivieren ausgewählt ist. Wenn dies nicht der Grund ist, wählen Sie es aus, und wählen Sie dann Übernehmen aus.

    10. Stellen Sie sicher, dass das Windows NT-Benutzerkonto, unter dem SQL Server ausgeführt wird, über die Berechtigung Vollzugriff für die Registrierungsschlüssel für dieses Objekt verfügt. Wenn die Berechtigungen nicht ausreichen oder die Registrierungsschlüssel falsch eingegeben werden, können beim Erstellen des COM-Objekts die folgenden Fehler auftreten:

      Ole Automation-Fehlerinformationen
      HRESULT: 0x80040154
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Klasse nicht registriert

      Ole Automation-Fehlerinformationen
      HRESULT: 0x80070005
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Der Zugriff wird verweigert.

      Ole Automation-Fehlerinformationen
      HRESULT: 0x80080005
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Fehler bei der Serverausführung

    11. Testen Und überprüfen Sie, ob die dllhost.exe-Datei ausgeführt und das COM-Objekt in seinen Prozessbereich geladen wird. Dies erfordert, dass sich das Windows NT Resource Kit auf dem Windows NT-Computer befindet, auf dem SQL Server ausgeführt wird. Öffnen Sie eine Eingabeaufforderung, und führen Sie an der Eingabeaufforderung die tlist.exe Datei aus, die alle Prozesse und die zugehörigen Prozessbezeichner oder Prozessbezeichner (PIDs) anzeigt. Verwenden Sie im Transact-SQL-Skript, in dem sp_OACreate ausgeführt wird und nachdem dieser Aufruf ausgeführt wurde, aber bevor das Skript beendet wird, folgendes, um den Abschluss des Skripts um weitere 20 Sekunden zu verzögern:

      WAITFOR DELAY '000:00:20'
      

      Führen Sie das Skript aus, navigieren Sie sofort zur Eingabeaufforderung, und führen Sie die tlist.exe-Datei aus. Notieren Sie sich die dllhost.exe PID. Führen Sie tlist.exe erneut aus, und übergeben Sie die PID als Parameter. Dies zeigt die DLLs an, die innerhalb des dllhost.exe Prozessbereichs geladen werden. Das DLL-basierte COM-Objekt sollte als ausgeführt in diesem Prozess aufgeführt werden. Nachdem das Skript zurückgegeben wurde, wird beim Erneuten Ausführen vontlist.exe angezeigt, dass der dllhost.exe Prozess nicht mehr ausgeführt wird.

      In der folgenden Beispielausgabe die ADODB. Das Verbindungsobjekt wird außerhalb des SQL Server Prozessbereichs erstellt. Dieser Momentaufnahme mit tlist.exe ausgeführt wurde, während das COM-Objekt im dllhost.exe Prozessbereich vorhanden war. Beachten Sie, dass das Modul msado15.dllgeladen wird, bei dem es sich um das Modul handelt, das das COM-Objekt enthält.

      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
      

References

Gespeicherte OLE-Automatisierungsprozeduren (Transact-SQL)