Запуск com-объекта на основе DLL за пределами процесса SQL Server
В этой статье описывается, как запустить COM-объект на основе DLL за пределами процесса SQL Server.
Исходная версия продукта: SQL Server
Исходный номер базы знаний: 198891
Итоги
Microsoft SQL Server предоставляет возможность загружать и запускать пользовательские объекты объектной модели компонентов (COM) с помощью набора хранимых процедур OLE Automation или с помощью расширенных хранимых процедур. По умолчанию COM-объекты на основе DLL загружаются как на сервере обработки, что означает, что COM-объекты загружаются не только в адресном пространстве памяти ПРОЦЕССА SQL Server, но и имеют полный доступ к этому адресного пространства памяти. Поэтому com-объект, загруженный в пространство обработки SQL Server, должен соответствовать тем же правилам, что и любой DLL-файл. Существует потенциал, что COM-объект может перезаписать память в процессе ИЛИ утечке ресурсов SQL Server, что приводит к нестабильности.
Если возникает подозрение, что COM-объект может повлиять на надежность процесса SQL Server, может потребоваться выполнить действия, описанные в этой статье, чтобы создать экземпляр COM-объекта за пределами пространства процессов SQL Server. Реализация спецификации DCOM распределенной объектной модели компонента для прозрачности расположения в операционной системе обеспечила возможность запуска com-объекта на основе DLL за пределами пространства процессов SQL Server.
Процесс запуска COM-объекта на основе DLL вне адресного пространства основного приложения называется удаленным взаимодействием. Для удаленного взаимодействия требуется, чтобы другой исполняемый файл был суррогатным процессом вместо исполняемого файла SQL Server. Исполняемый файл по умолчанию, используемый диспетчером управления службами DCOM (rpcss.exe), называется dllhost.exe. Структура поддержки DCOM использует файл dllhost.exe для загрузки библиотеки DLL в его пространство обработки, а затем использует пары прокси-сервера и заглушки для маршалирования запрошенного интерфейса прозрачно обратно клиенту, который в данном случае — SQL Server. Этот исполняемый файл может одновременно принимать несколько запросов интерфейса или метода. После завершения использования интерфейса диспетчер управления службами DCOM управляет очисткой и выгрузки файла dllhost.exe . Объекты COM не должны хранить сведения о состоянии между экземплярами.
Следующие шаги могут применяться к любому объекту COM на основе DLL, который создается в пространстве процессов SQL Server, независимо от того, создается ли экземпляр с помощью sp_OACreate
или расширенной хранимой процедуры.
Дополнительная информация
Сведения о двух основных методах, которые можно использовать для создания экземпляра com-объекта вне процесса, следует.
COM-клиент запрашивает удаленное взаимодействие объекта
Изменив способ вызова COM-объекта, можно запросить создание объекта за пределами адресного пространства SQL Server.
Если COM-объект загружается с помощью
sp_OACreate
процедуры, по умолчанию он загружается в процессе. Однако для этой процедуры существует необязательный третий параметр, который можно использовать для указания контекста создания объекта. Если этот параметр не указан, используется параметр по умолчанию 5 (5), то есть для запуска объекта внутри или за пределами процесса. Необходимо изменить параметр на четыре (4), указывающее на DCOM, что этот компонент должен выполняться как локальный исполняемый файл. Используйте синтаксис, аналогичный следующему примеру, чтобы явно сообщить DCOM о том, чтобы запустить COM-объект вне процесса с помощью хранимойsp_OACreate
процедуры:DECLARE @object int DECLARE @hr int EXEC @hr = sp_OACreate 'SQLOLE.SQLServer', @object OUT, 4
Если com-объект создается в расширенной хранимой процедуре, третий параметр
CoCreateInstance
илиCoCreateInstanceEx
может быть изменен наCLSCTX_LOCAL_SERVER
. Это показано в следующем примере кода с помощьюCoCreateInstance
:HRESULT hr = CoCreateInstance(CLSID_Test, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&piunknown);
Изменение реестра для принудительного удаленного взаимодействия объекта
Если вы не можете изменить COM-клиент, чтобы запросить, что объект создается вне процесса, существуют два разных метода, чтобы принудительно создать объект вне процесса.
Используйте средство просмотра объектов OLE/COM (oleview.exe), которое поставляется с Помощью Visual C++ и найдите ProgID в виде
OLEComponent.Object
всех объектов. Выберите COM-объект, а затем в меню "Объект " выберитеCoCreateInstance
"Флаги". Убедитесь, что выбран толькоCLSCTX_LOCAL_SERVER
выбранный параметр. Затем на вкладках "Реализация и сервер inproc" выберите "Использовать суррогатный процесс " и оставьте путь к пользовательскому суррогату пустым, что позволяет загружать файл dllhost.exe и библиотеку COM, переданную в его пространство процесса.Чтобы вручную обновить реестр, выполните следующие действия.
Предупреждение
Неправильное изменение реестра, выполненное с помощью редактора реестра или иным методом, может привести к серьезным проблемам. Из-за них может потребоваться переустановка операционной системы. Корпорация Майкрософт не может гарантировать, что эти проблемы удастся решить. Вносите изменения в реестр на ваш страх и риск.
Получите идентификатор класса (CLSID) объекта COM. CLSID — это 128-разрядное число и считается глобальным уникальным идентификатором (GUID), который используется для уникальной идентификации компонента, модуля или файла, содержащего этот COM-объект. При создании COM-объектов с помощью хранимых процедур OLE Automation первый параметр хранимой процедуры является программным идентификатором или идентификатором ProgID объекта OLE используется для получения CLSID. Эта символьная строка описывает класс объекта OLE и имеет следующую форму:
OLEComponent.Object
Вы можете использовать программный идентификатор для поиска идентификатора класса для COM-объекта.
Откройте редактор реестра (regedit.exe) и под
HKEY_CLASSES_ROOT
ключом используйтеFind
метод, чтобы найти ключ с именем <OLEComponent.Object>. Его можно найти на других уровнях, но он должен находиться на уровне непосредственно под нимHKEY_CLASSES_ROOT
. После поиска ключа разверните папку для имени ключа и увидите вложенный ключ с именем CLSID. Выберите папку, чтобы просмотреть значения в этом ключе. В правой части экрана — название по умолчанию. Данные для этого ключа должны находиться в следующей форме:{59F929A0-74D8-11D2-8CBC-08005A390B09}
Запишите это значение или скопируйте его в Блокнот. Включите квадратные скобки.
Перейдите по ключу
HKEY_CLASSES_ROOT\CLSID
и найдите подраздел с указанным номером GUID. После выделенияHKEY_CLASSES_ROOT\CLSID
ключа можно использовать функцию "Найти" в редакторе реестра (в меню "Изменить ") и вставить GUID в диалоговое окно "Поиск ". Убедитесь, что вы нашли правильный интерфейс, проверив подраздел InprocServer32 под этим ключом, который указывает на расположение COM-файла DLL. Если есть ключ TypeLib, проверьте это значение GUID. Это должно отличаться от того, что вы указали на шаге 1. В противном случае у вас есть GUID TypeLib, а не GUID для COM-объекта. В подразделе ProgID будет иметься значениеOLEComponent.Object.1
. Один из них предназначен только для этого примера и используется для сведений о версиях.В подключе GUID InprocServer32 убедитесь, что
ThreadingModel
значение существует и что оно имеет значение "Оба" или "Бесплатный", чтобы убедиться, что маршалинг понимает модель потоков объекта COM, чтобы обеспечить выполнение COM из пространства процессов SQL Server. Если значение неThreadingModel
задано или задано значение "Квартира", создание экземпляра com-объекта может быть не согласовано.Примечание.
При добавлении значения убедитесь, что перед реализацией
ThreadingModel
объект COM протестируете его.Выделите идентификатор GUID или подраздел под ключом
HKEY_CLASSES_ROOT\CLSID
. В меню "Изменить" выберите "Создать" и выберите "Строковое значение". В столбце Name введите AppID.Нажмите клавишу ВВОД , а затем вставьте идентификатор класса или номер GUID, который вы указали на шаге 1 в качестве значения. GUID должен находиться в фигурных скобках, как показано в следующем примере:
{59F929A0-74D8-11D2-8CBC-08005A390B09}
Идентификатор приложения AppID используется DCOM для связывания библиотеки DLL с исполняемым файлом.
Добавьте новый подраздел в
HKEY_CLASSES_ROOT\AppID
раздел и задайте его имя тому же идентификатору класса или номеру GUID с квадратными скобками, как вставлено на предыдущем шаге.Выделите имя GUID. В меню "Изменить" выберите "Создать" и выберите "Строковое значение". В столбце Name введите dllSurrogate.
Оставьте столбец данных пустым для этого значения. Так как столбец данных пуст, это сообщает DCOM запустить исполняемый файл по умолчанию, dllhost.exe и загрузить объект COM в его пространстве обработки.
Закройте Редактор реестра. Нажмите кнопку "Пуск", а затем нажмите кнопку "Выполнить". В диалоговом окне "Запуск" введите DCOMCNFG.
Нажмите клавишу ВВОД, чтобы открыть диалоговое окно "Свойства распределенной конфигурации COM". Щелкните вкладку "Свойства по умолчанию" и убедитесь, что на этом компьютере выбран параметр "Включить распределенный COM ". Если это не так, выберите его и нажмите кнопку "Применить".
Убедитесь, что учетная запись пользователя Windows NT, на которую выполняется SQL Server, имеет разрешение на полный доступ к разделам реестра для этого объекта. Если разрешения недостаточно или разделы реестра вводимы неправильно, при создании COM-объекта могут возникнуть следующие ошибки:
Сведения об ошибке OLE Automation
HRESULT: 0x80040154
Источник: расширенная процедура ODSOLE
Описание: класс не зарегистрированСведения об ошибке OLE Automation
HRESULT: 0x80070005
Источник: расширенная процедура ODSOLE
Описание. Доступ запрещен.Сведения об ошибке OLE Automation
HRESULT: 0x80080005
Источник: расширенная процедура ODSOLE
Описание: сбой выполнения сервераПроверьте и проверьте, выполняется ли файл dllhost.exe и загружается COM-объект в его пространстве обработки. Для этого требуется, чтобы набор ресурсов Windows NT был на компьютере Windows NT, на котором работает SQL Server. Откройте командную строку и в командной строке запустите файл tlist.exe , в котором показаны все процессы и связанные с ними идентификаторы процесса или идентификаторы процессов (PID). В скрипте Transact-SQL, где
sp_OACreate
выполняется и после выполнения этого вызова, но до завершения скрипта используйте следующее, чтобы отложить завершение скрипта в течение дополнительных 20 секунд:WAITFOR DELAY '000:00:20'
Запустите скрипт и немедленно перейдите в командную строку и запустите файл tlist.exe . Обратите внимание на идентификатор dllhost.exe . Повторно выполните tlist.exe и передайте PID в качестве параметра. В этом разделе показаны библиотеки DLL, загруженные в пространстве процесса dllhost.exe . Com-объект на основе DLL должен быть указан как запущенный в рамках этого процесса. После возврата скрипта выполнение tlist.exe снова показывает, что процесс dllhost.exe больше не выполняется.
В следующем примере выходных данных ADODB. Объект подключения создается вне пространства процессов SQL Server. Этот моментальный снимок с помощью tlist.exe был выполнен, пока объект COM существовал в пространстве процесса dllhost.exe . Обратите внимание, что модуль msado15.dll, который является модулем, который содержит COM-объект, загружается.
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