Köra ett DLL-baserat COM-objekt utanför SQL Server-processen
I den här artikeln beskrivs hur du kör ett DLL-baserat COM-objekt utanför SQL Server-processen.
Ursprunglig produktversion: SQL Server
Ursprungligt KB-nummer: 198891
Sammanfattning
Microsoft SQL Server ger möjlighet att läsa in och köra anpassade COM-objekt (Component Object Model) via en uppsättning lagrade OLE Automation-procedurer eller genom utökade lagrade procedurer. Som standard läses DLL-baserade COM-objekt in som i processservern, vilket innebär att COM-objekten inte bara läses in i SQL Server-processens minnesadressutrymme, utan de har också fullständig åtkomst till det här minnesadressutrymmet. Därför måste ett COM-objekt som läses in i SQL Server-processutrymmet följa samma regler som alla DLL-filer. Det finns en potential att ett COM-objekt kan skriva över minne i SQL Server-processen eller läcka resurser, vilket orsakar instabilitet.
Om det finns misstanke om att ett COM-objekt kan påverka robustheten i SQL Server-processen kanske du vill använda stegen i den här artikeln för att instansiera COM-objektet utanför SQL Server-processutrymmet. Implementeringen av DCOM-specifikationen (Distributed Component Object Model) för Platstransparens i operativsystemet har gett möjlighet att köra ett DLL-baserat COM-objekt utanför SQL Server-processutrymmet.
Processen att köra ett DLL-baserat COM-objekt utanför huvudprogrammets adressutrymme kallas fjärrkommunikation. Fjärrkommunikation kräver att en annan körbar fil är en surrogatprocess i stället för den körbara SQL Server-filen. Den körbara standardkörningen som används av DCOM Service Control Manager (rpcss.exe) heter dllhost.exe. DCOM-stödstrukturen använder dllhost.exe-filen för att läsa in DLL:n i dess processutrymme och använder sedan proxy/stub-par för att konvertera det begärda gränssnittet transparent tillbaka till klienten, vilket i det här fallet är SQL Server. Den här körbara filen kan acceptera flera gränssnitts-/metodbegäranden samtidigt. När gränssnittsanvändningen är klar hanterar DCOM Service Control Manager (SCM) rensningen och avlastningen av dllhost.exe-filen. COM-objekt bör inte förväntas behålla tillståndsinformation mellan instansieringar.
Följande steg kan gälla för alla DLL-baserade COM-objekt som skapas i SQL Server-processutrymmet, oavsett om det instansieras via sp_OACreate
eller en utökad lagrad procedur.
Mer information
Information om de två grundläggande metoder som du kan använda för att instansiera COM-objektet ur process följer.
COM-klienten begär fjärrkommunikation av objektet
Genom att ändra hur du anropar COM-objektet kan du begära att objektet skapas utanför SQL Server-adressutrymmet.
Om COM-objektet läses in med hjälp av proceduren
sp_OACreate
läses det som standard in i processen. Det finns dock en valfri tredje parameter i den här proceduren som du kan använda för att ange kontexten för var objektet ska skapas. Om den här parametern inte anges används standardinställningen fem (5), vilket innebär att objektet körs antingen inuti eller utanför processen. Du måste ändra parametern till fyra (4), vilket anger för DCOM att den här komponenten ska köras som en lokal körbar fil. Använd syntax som liknar följande exempel för att uttryckligen informera DCOM om att köra COM-objektet ur processen med hjälp av densp_OACreate
lagrade proceduren:DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
Om COM-objektet skapas inom en utökad lagrad procedur kan den tredje parametern
CoCreateInstance
för ellerCoCreateInstanceEx
ändras tillCLSCTX_LOCAL_SERVER
. Detta visas i följande kodexempel med hjälp avCoCreateInstance
:HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
Ändra registret för att tvinga fjärrkommunikation av objektet
Om du inte kan ändra COM-klienten för att begära att objektet ska skapas utan process finns det två olika metoder för att tvinga objektet att skapas ur processen.
Använd ole-/COM-objektvisaren (oleview.exe) som levereras med Visual C++ och leta upp ProgID i form av
OLEComponent.Object
under Alla objekt. Välj COM-objektet och väljCoCreateInstance
sedan Flaggor på menyn Objekt. Kontrollera att endastCLSCTX_LOCAL_SERVER
är markerat. Under flikarna Implementering och Inproc Server väljer du Använd surrogatprocess och lämnar sökvägen till anpassad surrogat tom, vilket gör att dllhost.exe-filen kan läsas in och COM DLL-filen tas med i dess processutrymme.Använd följande steg för att uppdatera registret manuellt.
Varning
Varning: Allvarliga problem kan uppstå om du felaktigt ändrar registret med hjälp av Registereditorn eller med en annan metod. Dessa problem kan kräva att du installerar om operativsystemet. Microsoft kan inte garantera att problemen kan lösas. Ändra registret på egen risk.
Hämta klassidentifieraren (CLSID) för COM-objektet. CLSID är ett 128-bitarsnummer och anses vara en globalt unik identifierare (GUID) som används för att unikt identifiera komponenten, modulen eller filen som innehåller det här COM-objektet. När du skapar COM-objekt med hjälp av OLE Automation-lagrade procedurer är den första parametern i den lagrade proceduren en programmatisk identifierare eller progID för OLE-objektet används för att härleda CLSID. Den här teckensträngen beskriver klassen för OLE-objektet och har följande formulär:
OLEComponent.Object
Du kan använda den programmatiska identifieraren för att hitta klassidentifieraren för ett COM-objekt.
Öppna Registereditorn (regedit.exe) och använd
Find
metoden underHKEY_CLASSES_ROOT
nyckeln för att hitta en nyckel med namnet på ditt <OLEComponent.Object>. Du hittar den på andra nivåer, men den bör finnas på nivån direkt underHKEY_CLASSES_ROOT
. När du har hittat nyckeln expanderar du mappen för nyckelnamnet och du bör se en undernyckel med namnet CLSID. Välj den mappen om du vill se värdena i den nyckeln. Till höger på skärmen finns en rubrik med namnet Standard. Data för den nyckeln ska vara i följande form:{59F929A0-74D8-11D2-8CBC-08005A390B09}
Anteckna det här värdet eller kopiera det till Anteckningar. Ta med hakparenteserna.
Navigera under
HKEY_CLASSES_ROOT\CLSID
nyckeln och leta reda på undernyckeln med det här GUID-numret. När du har markeratHKEY_CLASSES_ROOT\CLSID
nyckeln kan du använda funktionen Sök i Registereditorn (under menyn Redigera ) och klistra in GUID i dialogrutan Sök . Kontrollera att du har hittat rätt gränssnitt genom att granska undernyckeln InprocServer32 under den här nyckeln, som pekar på platsen för DIN COM DLL-fil. Om det finns en TypeLib-nyckel kontrollerar du det här GUID-värdet. Detta bör skilja sig från vad du antecknade i steg 1. Annars har du TypeLib GUID och inte GUID för COM-objektet. ProgID-undernyckeln har värdetOLEComponent.Object.1
. Den i slutet är endast för det här exemplet och används för versionshanteringsinformation.Under GUID:ns InprocServer32-undernyckel kontrollerar du att ett
ThreadingModel
värde finns och att det är inställt på antingen Båda eller Kostnadsfri för att se till att marskalkningen förstår trådningsmodellen för COM-objektet för att aktivera körning av COM från SQL Server-processutrymmet. Om det inte finns någotThreadingModel
värde eller om det har angetts till Lägenhet är COM-objektens instansiering kanske inte konsekvent.Kommentar
Om du lägger till värdet
ThreadingModel
kontrollerar du att du testar DITT COM-objekt innan du implementerar det.Markera GUID-numret/undernyckeln
HKEY_CLASSES_ROOT\CLSID
under nyckeln. På menyn Redigera väljer du Nytt och sedan Strängvärde. Under kolumnen Namn skriver du AppID.Tryck på RETUR och infoga sedan klassidentifieraren eller GUID-numret som du antecknade från steg 1 som värde. GUID:t bör finnas inom klammerparenteserna som i följande exempel:
{59F929A0-74D8-11D2-8CBC-08005A390B09}
Programidentifieraren AppID används av DCOM för att associera DLL:en med en körbar fil.
Lägg till en ny undernyckel under
HKEY_CLASSES_ROOT\AppID
och ange dess namn till samma klassidentifierare eller GUID-nummer med hakparenteserna som infogades i föregående steg.Markera GUID-namnet. På menyn Redigera väljer du Nytt och sedan Strängvärde. Under kolumnen Namn skriver du dllSurrogate.
Lämna kolumnen Data tom för det här värdet. Eftersom datakolumnen är tom informerar detta DCOM om att köra den körbara standardfilen dllhost.exe och läsa in COM-objektet inom dess processutrymme.
Stäng Registereditorn. Klicka på Start och välj sedan Kör. I dialogrutan Kör skriver du DCOMCNFG.
Tryck på RETUR för att öppna dialogrutan Distributed COM Configuration Properties (Distribuerade COM-konfigurationsegenskaper ). Klicka på fliken Standardegenskaper och se till att Aktivera distribuerad COM på den här datorn är markerat. Om den inte är det väljer du den och väljer sedan Använd.
Kontrollera att det Windows NT-användarkonto som SQL Server körs under har fullständig behörighet för registernycklarna för det här objektet. Om behörigheterna inte räcker eller om registernycklarna matas in felaktigt kan följande fel inträffa när du skapar COM-objektet:
Ole Automation-felinformation
HRESULT: 0x80040154
Källa: ODSOLE Extended Procedure
Beskrivning: Klassen är inte registreradOle Automation-felinformation
HRESULT: 0x80070005
Källa: ODSOLE Extended Procedure
Beskrivning: Åtkomst nekas.Ole Automation-felinformation
HRESULT: 0x80080005
Källa: ODSOLE Extended Procedure
Beskrivning: Serverkörningen misslyckadesTesta och se om det här kör dllhost.exe-filen och läser in COM-objektet i dess processutrymme. Detta kräver att Windows NT Resource Kit finns på den Windows NT-dator där SQL Server körs. Öppna en kommandotolk och kör tlist.exe-filen från kommandotolken, som visar alla processer och deras associerade processidentifierare eller processidentifierare (PID). I Transact-SQL-skriptet där
sp_OACreate
körs och efter att anropet körs, men innan skriptet slutar använder du följande för att fördröja skriptets slutförande i ytterligare 20 sekunder:WAITFOR DELAY '000:00:20'
Kör skriptet och navigera omedelbart till kommandotolken och kör filen tlist.exe . Observera dllhost.exe PID. Kör om tlist.exe och skicka PID:t som en parameter. Detta visar DLL:er som läses in inom dllhost.exe processutrymme. Det DLL-baserade COM-objektet bör visas som körs i den här processen. När skriptet har returnerats visar körningen av tlist.exe igen att dllhost.exe processen inte längre körs.
I följande exempelutdata, ADODB. Anslutningsobjekt skapas utanför SQL Server-processutrymmet. Den här ögonblicksbilden med hjälp av tlist.exe utfördes medan COM-objektet fanns i dllhost.exe processutrymme. Observera att modulen msado15.dll, som är modulen som innehåller COM-objektet, läses in.
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