Een OP DLL gebaseerd COM-object buiten het SQL Server-proces uitvoeren
In dit artikel wordt beschreven hoe u een OP DLL gebaseerd COM-object uitvoert buiten het SQL Server-proces.
Oorspronkelijke productversie: SQL Server
Oorspronkelijk KB-nummer: 198891
Samenvatting
Microsoft SQL Server biedt de mogelijkheid om aangepaste COM-objecten (Component Object Model) te laden en uit te voeren via een set opgeslagen OLE Automation-procedures of via uitgebreide opgeslagen procedures. COM-objecten op basis van DLL worden standaard geladen als op de processerver, wat betekent dat de COM-objecten niet alleen worden geladen binnen de geheugenadresruimte van het SQL Server-procesgeheugen, maar ze hebben ook volledige toegang tot deze geheugenadresruimte. Daarom moet een COM-object dat in de SQL Server-procesruimte is geladen, voldoen aan dezelfde regels als elk DLL-bestand. Er is een potentieel dat een COM-object geheugen kan overschrijven binnen het SQL Server-proces of resources kan lekken, wat instabiliteit veroorzaakt.
Als er vermoedens zijn dat een COM-object de robuustheid van het SQL Server-proces beïnvloedt, kunt u de stappen in dit artikel gebruiken om het COM-object buiten de SQL Server-procesruimte te instantiëren. Implementatie van de DCOM-specificatie (Distributed Component Object Model) van Location Transparency in het besturingssysteem biedt de mogelijkheid om een OP DLL gebaseerd COM-object buiten de SQL Server-procesruimte uit te voeren.
Het proces voor het uitvoeren van een OP DLL gebaseerd COM-object buiten de adresruimte van de hoofdtoepassing wordt remoting genoemd. Externe communicatie vereist dat een ander uitvoerbaar bestand een surrogaatproces is in plaats van het uitvoerbare SQL Server-bestand. Het standaard uitvoerbare bestand dat wordt gebruikt door DCOM Service Control Manager (rpcss.exe) heet dllhost.exe. De DCOM-ondersteuningsstructuur maakt gebruik van het dllhost.exe-bestand om het DLL-bestand in de procesruimte te laden en gebruikt vervolgens proxy-/stub-paren om de aangevraagde interface transparant terug te zetten naar de client, wat in dit geval de SQL Server is. Dit uitvoerbare bestand kan gelijktijdig meerdere interface-/methodeaanvragen accepteren. Nadat het gebruik van de interface is voltooid, beheert de DCOM Service Control Manager (SCM) het opschonen en lossen van het dllhost.exe bestand. COM-objecten mogen geen statusinformatie bewaren tussen instantiëringen.
De volgende stappen kunnen van toepassing zijn op elk OP DLL gebaseerd COM-object dat wordt gemaakt in de SQL Server-procesruimte, ongeacht of het wordt geïnstantieerd via sp_OACreate
of een uitgebreide opgeslagen procedure.
Meer informatie
Informatie over de twee basismethoden die u kunt gebruiken om het COM-object uit het proces te instantiëren, volgt.
COM-client vraagt om externe communicatie van het object
Door de manier te wijzigen waarop u het COM-object aanroept, kunt u aanvragen dat het object buiten de SQL Server-adresruimte wordt gemaakt.
Als het COM-object wordt geladen met behulp van de
sp_OACreate
procedure, wordt het standaard in proces geladen. Er is echter een optionele derde parameter voor deze procedure die u kunt gebruiken om de context aan te geven van waar het object moet worden gemaakt. Als deze parameter niet is opgegeven, wordt de standaardinstelling van vijf (5) gebruikt, wat betekent dat het object binnen of buiten het proces wordt uitgevoerd. U moet de parameter wijzigen in vier (4), wat aangeeft aan DCOM dat dit onderdeel moet worden uitgevoerd als een lokaal uitvoerbaar bestand. Gebruik de syntaxis die vergelijkbaar is met het volgende voorbeeld om DCOM expliciet te informeren dat het COM-object niet meer kan worden verwerkt met behulp van desp_OACreate
opgeslagen procedure:DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
Als het COM-object wordt gemaakt in een uitgebreide opgeslagen procedure, kan de derde parameter van
CoCreateInstance
ofCoCreateInstanceEx
worden gewijzigd inCLSCTX_LOCAL_SERVER
. Dit wordt weergegeven in het volgende codevoorbeeld met behulp vanCoCreateInstance
:HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
Register wijzigen om externe toegang van het object af te dwingen
Als u de COM-client niet kunt wijzigen om aan te vragen dat het object buiten het proces wordt gemaakt, bestaan er twee verschillende methoden om af te dwingen dat het object buiten het proces wordt gemaakt.
Gebruik de OLE/COM-objectviewer (oleview.exe) die is verzonden met Visual C++ en zoek de ProgID in de vorm van
OLEComponent.Object
onder Alle objecten. Selecteer het COM-object en selecteer vervolgens in het menu Object de optieCoCreateInstance
Vlaggen. Zorg ervoor dat alleenCLSCTX_LOCAL_SERVER
deze optie is geselecteerd. Selecteer vervolgens onder de tabbladen Implementatie en Inproc-server de optie Surrogaatproces gebruiken en laat het pad naar aangepaste surrogaat leeg, zodat het dllhost.exe bestand kan worden geladen en de COM-DLL binnen de procesruimte wordt gebracht.Gebruik de volgende stappen om het register handmatig bij te werken.
Waarschuwing
Er kunnen zich ernstige problemen voordoen als u het register met de Register-editor of met een andere methode foutief wijzigt. Wellicht moet u door deze problemen het besturingssysteem opnieuw installeren. Microsoft kan niet garanderen dat deze problemen kunnen worden opgelost. Het wijzigen van het register is op eigen risico.
Haal de klasse-id (CLSID) van het COM-object op. De CLSID is een 128-bits getal en wordt beschouwd als een GUID (Globally Unique Identifier) die wordt gebruikt om het onderdeel, de module of het bestand dat dit COM-object bevat, uniek te identificeren. Wanneer u COM-objecten maakt met behulp van de opgeslagen OLE Automation-procedures, is de eerste parameter voor de opgeslagen procedure een programmatische id of wordt de ProgID van het OLE-object gebruikt om de CLSID af te leiden. Deze tekenreeks beschrijft de klasse van het OLE-object en heeft de volgende vorm:
OLEComponent.Object
U kunt de programmatische id gebruiken om de klasse-id voor een COM-object te vinden.
Open de Register-editor (regedit.exe) en gebruik onder de
HKEY_CLASSES_ROOT
sleutel deFind
methode om een sleutel te zoeken met de naam van uw <OLEComponent.Object>. U vindt het op andere niveaus, maar het moet zich direct onder hetHKEY_CLASSES_ROOT
niveau bevinden. Nadat u de sleutel hebt gevonden, vouwt u de map voor de sleutelnaam uit en ziet u een subsleutel met de naam CLSID. Selecteer die map om de waarden in die sleutel weer te geven. Aan de rechterkant van het scherm bevindt zich een titel met de naam Default. De gegevens voor die sleutel moeten de volgende vorm hebben:{59F929A0-74D8-11D2-8CBC-08005A390B09}
Noteer deze waarde of kopieer deze naar Kladblok. Neem de haken op.
Navigeer onder de
HKEY_CLASSES_ROOT\CLSID
sleutel en zoek de subsleutel met dit GUID-nummer. Nadat u deHKEY_CLASSES_ROOT\CLSID
sleutel hebt gemarkeerd, kunt u de functie Zoeken in registereditor (onder het menu Bewerken ) gebruiken en de GUID in het dialoogvenster Zoeken plakken. Zorg ervoor dat u de juiste interface hebt gevonden door de Subsleutel InprocServer32 onder deze sleutel te inspecteren, die verwijst naar de locatie van uw COM DLL-bestand. Als er een TypeLib-sleutel is, controleert u deze GUID-waarde. Dit moet afwijken van wat u in stap 1 hebt genoteerd. Anders hebt u de TypeLib-GUID en niet de GUID voor het COM-object. De ProgID-subsleutel heeft een waarde vanOLEComponent.Object.1
. De regel aan het einde is alleen voor dit voorbeeld en wordt gebruikt voor versiebeheergegevens.Zorg er onder de Subsleutel InprocServer32 van de GUID voor dat er een
ThreadingModel
waarde bestaat en dat deze is ingesteld op Beide of Vrij om ervoor te zorgen dat de marshaling het threadingmodel van het COM-object begrijpt om de uitvoering van COM uit de SQL Server-procesruimte mogelijk te maken. Als er geenThreadingModel
waarde is of is ingesteld op Apartment, is COM-object instantiëring mogelijk niet consistent.Notitie
Als u de
ThreadingModel
waarde toevoegt, moet u ervoor zorgen dat u uw COM-object test voordat u het implementeert.Markeer het GUID-nummer/de subsleutel onder de
HKEY_CLASSES_ROOT\CLSID
sleutel. Selecteer Nieuw in het menu Bewerken en selecteer vervolgens Tekenreekswaarde. Typ AppID onder de kolom Naam.Druk op ENTER en voeg vervolgens het klasse-id of GUID-nummer in dat u hebt genoteerd in stap 1 als waarde. De GUID moet zich binnen de accolades bevinden, zoals in het volgende voorbeeld:
{59F929A0-74D8-11D2-8CBC-08005A390B09}
De app-id van de toepassing wordt door DCOM gebruikt om het DLL-bestand te koppelen aan een uitvoerbaar bestand.
Voeg een nieuwe subsleutel toe onder de
HKEY_CLASSES_ROOT\AppID
en stel de naam ervan in op dezelfde klasse-id of GUID-nummer met de vierkante haken die in de vorige stap zijn ingevoegd.Markeer de GUID-naam. Selecteer Nieuw in het menu Bewerken en selecteer vervolgens Tekenreekswaarde. Typ onder de kolom Naam dllSurrogate.
Laat de kolom Gegevens leeg voor deze waarde. Omdat de gegevenskolom leeg is, informeert DCOM om het standaard uitvoerbare bestand uit te voeren, dllhost.exe en het COM-object in de procesruimte te laden.
Sluit de Register-editor. Klik op Start en selecteer Uitvoeren. Typ DCOMCNFG in het dialoogvenster Uitvoeren.
Druk op Enter om het dialoogvenster Gedistribueerde COM-configuratie-eigenschappen te openen. Klik op het tabblad Standaardeigenschappen en zorg ervoor dat Gedistribueerde COM op deze computer inschakelen is geselecteerd. Als dat niet het is, selecteert u deze en selecteert u Vervolgens Toepassen.
Zorg ervoor dat het Windows NT-gebruikersaccount waaronder SQL Server wordt uitgevoerd, de machtiging Volledig beheer heeft voor de registersleutels voor dit object. Als de machtigingen niet voldoende zijn of als de registersleutels onjuist worden ingevoerd, kunnen de volgende fouten optreden wanneer u het COM-object maakt:
INFORMATIE OVER OLE-automatiseringsfouten
HRESULT: 0x80040154
Bron: ODSOLE Uitgebreide procedure
Beschrijving: Klasse niet geregistreerdINFORMATIE OVER OLE-automatiseringsfouten
HRESULT: 0x80070005
Bron: ODSOLE Uitgebreide procedure
Beschrijving: De toegang is geweigerd.INFORMATIE OVER OLE-automatiseringsfouten
HRESULT: 0x80080005
Bron: ODSOLE Uitgebreide procedure
Beschrijving: serveruitvoering is misluktTest en kijk of het dllhost.exe-bestand wordt uitgevoerd en laad het COM-object in de procesruimte. Hiervoor moet de Windows NT Resource Kit zich op de Windows NT-computer bevinden waarop SQL Server wordt uitgevoerd. Open een opdrachtprompt en voer vanaf de opdrachtprompt het tlist.exe-bestand uit, waarin alle processen en de bijbehorende proces-id's of proces-id's (PID's) worden weergegeven. In het Transact-SQL-script waar
sp_OACreate
deze wordt uitgevoerd en nadat deze aanroep is uitgevoerd, maar voordat het script eindigt, gebruikt u het volgende om de voltooiing van het script gedurende 20 seconden uit te stellen:WAITFOR DELAY '000:00:20'
Voer het script uit en navigeer onmiddellijk naar de opdrachtprompt en voer het tlist.exe-bestand uit. Noteer de dllhost.exe PID. Voer tlist.exe opnieuw uit en geef de PID door als parameter. Hier ziet u de DLL's die in de dllhost.exe procesruimte zijn geladen. Het OP DLL gebaseerde COM-object moet worden weergegeven als actief binnen dit proces. Nadat het script is geretourneerd, wordt opnieuw tlist.exe uitgevoerd dat het dllhost.exe proces niet meer wordt uitgevoerd.
In de volgende voorbeelduitvoer, de ADODB. Verbindingsobject wordt buiten de SQL Server-procesruimte gemaakt. Deze momentopname met behulp van tlist.exe is uitgevoerd terwijl het COM-object bestond in de dllhost.exe procesruimte. U ziet dat de module msado15.dll, de module die het COM-object bevat, is geladen.
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