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 dersp_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
oderCoCreateInstanceEx
geändert werden inCLSCTX_LOCAL_SERVER
. Dies wird im folgenden Codebeispiel unter Verwendung vonCoCreateInstance
: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" ausCoCreateInstance
. Stellen Sie sicher, dass nurCLSCTX_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.
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
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 derFind
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 derHKEY_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.
Navigieren Sie unter dem
HKEY_CLASSES_ROOT\CLSID
Schlüssel, und suchen Sie den Unterschlüssel mit dieser GUID-Nummer. Nachdem Sie denHKEY_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 vonOLEComponent.Object.1
. Dies ist nur für dieses Beispiel vorgesehen und wird für Versionsverwaltungsinformationen verwendet.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 keinThreadingModel
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.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.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.
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.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.
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.
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 registriertOLE-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ührungTesten 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