Freigeben über


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 durch erweiterte gespeicherte Prozeduren zu laden und auszuführen. Standardmäßig werden DLL-basierte COM-Objekte wie auf dem Prozessserver geladen, was bedeutet, dass die COM-Objekte nicht nur im SQL Server-Prozessspeicherspeicherspeicherraum geladen werden, sondern auch vollzugriff auf diesen Speicheradressraum haben. Daher muss ein IM SQL Server-Prozessbereich geladenes COM-Objekt dieselben Regeln wie jede DLL-Datei einhalten. Es gibt ein Potenzial, dass ein COM-Objekt Speicher innerhalb des SQL Server-Prozesses oder Speicherlecks überschreiben könnte, was zu Instabilität führt.

Wenn ein COM-Objekt die Stabilität des SQL Server-Prozesses beeinträchtigen kann, sollten Sie die Schritte in diesem Artikel verwenden, um das COM-Objekt außerhalb des SQL Server-Prozessbereichs instanziieren zu können. 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.

Der Prozess der Ausführung eines DLL-basierten COM-Objekts außerhalb des Adressraums der Hauptanwendung wird als Remoting bezeichnet. Remoting erfordert, dass eine andere ausführbare Datei anstelle der ausführbaren SQL Server-Datei ein Ersatzprozess ist. Die vom DCOM Service Control Manager (rpcss.exe) verwendete Standarddatei wird dllhost.exe benannt. Die DCOM-Unterstützungsstruktur verwendet die dllhost.exe Datei, um die DLL in den Prozessbereich zu laden, und verwendet dann Proxy-/Stubpaare, um die angeforderte Schnittstelle transparent zurück an den Client zu marshallen, was in diesem Fall der SQL Server ist. Diese ausführbare Datei kann mehrere Schnittstellen-/Methodenanforderungen gleichzeitig akzeptieren. Nach Abschluss der Schnittstellenverwendung verwaltet der DCOM Service Control Manager (SCM) die Bereinigung und Entladung der dllhost.exe Datei. COM-Objekte sollten nicht erwartet werden, dass Statusinformationen zwischen Instanziierungen aufbewahrt werden.

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

Weitere Informationen

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

COM-Client fordert Remoting des Objekts an

Durch Ändern der Art und Weise, 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 in den Prozess geladen. Für diese Prozedur gibt es jedoch einen optionalen dritten Parameter, mit dem Sie den Kontext angeben können, in dem das Objekt erstellt werden soll. Wenn dieser Parameter nicht angegeben ist, wird die Standardeinstellung von fünf (5) verwendet, was bedeutet, dass das Objekt innerhalb oder außerhalb des Prozesses ausgeführt werden soll. 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 die Syntax, die dem folgenden Beispiel ähnelt, um DCOM explizit darüber zu informieren, das COM-Objekt mithilfe der sp_OACreate gespeicherten 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 geändert werden in CLSCTX_LOCAL_SERVER. Dies wird im folgenden Codebeispiel unter Verwendung von CoCreateInstance:

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

Ändern der Registrierung, um das Remoting des Objekts zu erzwingen

Wenn Sie den COM-Client nicht ändern können, um anzufordern, dass das Objekt aus dem Prozess erstellt wird, sind zwei verschiedene Methoden vorhanden, um zu erzwingen, dass das Objekt aus dem Prozess erstellt wird.

  • Verwenden Sie den OLE/COM-Objekt-Viewer (oleview.exe), der mit Visual C++ ausgeliefert wird, und suchen Sie die ProgID in Form von OLEComponent.Object unter "Alle Objekte". Wählen Sie das COM-Objekt aus, und wählen Sie 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 unter den Registerkarten "Implementierung " und "Inproc Server " die Option "Surrogate-Prozess verwenden" aus, und lassen Sie den Pfad zum benutzerdefinierten Surrogate leer, sodass die dllhost.exe Datei geladen werden kann und die COM-DLL im Prozessbereich enthalten ist.

  • 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 die Klassen-ID (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 OLE-Automatisierungsprozeduren ist der erste Parameter für die gespeicherte Prozedur ein programmgesteuerter Bezeichner oder die ProgID des OLE-Objekts zum Ableiten der CLSID. Diese Zeichenfolge beschreibt die Klasse des OLE-Objekts und weist die folgende Form auf:

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

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

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

      Notieren Sie 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 InprocServer32-Unterschlüssel 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 anders sein als das, was Sie in Schritt 1 angegeben haben. Andernfalls verfügen Sie über die TypeLib-GUID und nicht über die GUID für das COM-Objekt. Der ProgID-Unterschlüssel hat einen Wert von OLEComponent.Object.1. Dies ist nur für dieses Beispiel vorgesehen und wird für Versionsverwaltungsinformationen verwendet.

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

      Notiz

      Wenn Sie den Wert hinzufügen, stellen Sie sicher, dass Sie Ihr COM-Objekt vor der ThreadingModel 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 unter der Spalte "Name" "AppID" ein.

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

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

      Die Anwendungs-ID AppID wird von DCOM verwendet, um die DLL einer ausführbaren Datei zuzuordnen.

    7. Fügen Sie unter dem HKEY_CLASSES_ROOT\AppID neuen Unterschlüssel einen neuen Unterschlüssel hinzu, und legen Sie dessen Namen auf dieselbe Klassen-ID oder GUID-Nummer fest, wobei die Klammern wie 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 unter der Spalte "Name" "dllSurrogate" ein.

      Lassen Sie die Datenspalte für diesen Wert leer. Da die Datenspalte leer ist, wird DCOM informiert, die standardmäßige ausführbare Datei auszuführen, dllhost.exe 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 Befehl "DCOMCNFG" ein.

      Drücken Sie die EINGABETASTE , um das Dialogfeld "Verteilte COM-Konfigurationseigenschaften " 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 Der Grund ist, wählen Sie sie 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 die folgenden Fehler auftreten, wenn Sie das COM-Objekt erstellen:

      OLE-Automatisierungsfehlerinformationen
      HRESULT: 0x80040154
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Klasse nicht registriert

      OLE-Automatisierungsfehlerinformationen
      HRESULT: 0x80070005
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Der Zugriff wurde verweigert.

      OLE-Automatisierungsfehlerinformationen
      HRESULT: 0x80080005
      Quelle: ODSOLE Extended Procedure
      Beschreibung: Fehler bei der Serverausführung

    11. Testen Sie, ob dies die dllhost.exe Datei ausführt, und laden Sie das COM-Objekt im Prozessbereich. 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 (Process Identifiers, PIDs) anzeigt. Verwenden Sie im Transact-SQL-Skript, in dem sp_OACreate und nach dem Aufruf ausgeführt wird, aber bevor das Skript endet, folgendes, um den Abschluss des Skripts für weitere 20 Sekunden zu verzögern:

      WAITFOR DELAY '000:00:20'
      

      Führen Sie das Skript aus, und navigieren Sie sofort zur Eingabeaufforderung, und führen Sie die tlist.exe Datei aus. Beachten Sie die dllhost.exe PID. Führen Sie tlist.exe erneut aus, und übergeben Sie die PID als Parameter. Dies zeigt die DLLs, die innerhalb des dllhost.exe Prozessbereichs geladen werden. Das DLL-basierte COM-Objekt sollte innerhalb dieses Prozesses als ausgeführt aufgeführt werden. Nach dem Zurückgeben des Skripts wird durch ausführen tlist.exe erneut angezeigt, dass der dllhost.exe Prozess nicht mehr ausgeführt wird.

      In der folgenden Beispielausgabe, der ADODB. Das Verbindungsobjekt wird außerhalb des SQL Server-Prozessbereichs erstellt. Diese Momentaufnahme mit tlist.exe wurde ausgeführt, während das COM-Objekt im dllhost.exe Prozessbereich vorhanden war. Beachten Sie, dass das Modul msado15.dll( das Modul, das das COM-Objekt enthält) geladen wird.

      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)