Запуск 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 за пределами адресного пространства приложения main называется удаленным взаимодействием. Для удаленного взаимодействия требуется, чтобы другой исполняемый файл был суррогатным процессом вместо SQL Server исполняемого файла. Исполняемый файл по умолчанию, используемый диспетчером управления службами DCOM (rpcss.exe), называется dllhost.exe. Структура поддержки DCOM использует файлdllhost.exe для загрузки библиотеки DLL в пространство процесса, а затем использует пары прокси-заглушки для прозрачного маршалирования запрошенного интерфейса обратно в клиент, который в данном случае является SQL Server. Этот исполняемый файл может одновременно принимать несколько запросов интерфейса или метода. После завершения использования интерфейса диспетчер управления службой DCOM (SCM) управляет очисткой и выгрузки файлаdllhost.exe . Не следует ожидать, что com-объекты будут хранить сведения о состоянии между экземплярами.

Приведенные ниже действия могут применяться к любому объекту COM на основе DLL, который создается в SQL Server пространстве процесса, независимо от того, создается ли он с помощью sp_OACreate или расширенной хранимой процедуры.

Дополнительная информация

Ниже приведены сведения о двух основных методах, которые можно использовать для создания экземпляра COM-объекта вне процесса.

COM-клиент запрашивает удаленное взаимодействие объекта

Изменив способ вызова com-объекта, можно запросить создание объекта за пределами SQL Server адресного пространства.

  • Если COM-объект загружается с помощью sp_OACreate процедуры, по умолчанию он загружается в процессе. Однако для этой процедуры существует необязательный третий параметр, который можно использовать для указания контекста создания объекта. Если этот параметр не указан, используется значение по умолчанию пять (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 в пространство процесса.

  • Чтобы вручную обновить реестр, выполните следующие действия.

    Предупреждение

    При неправильном изменении реестра с использованием редактора реестра или другого способа могут случиться серьезные проблемы. Из-за них может потребоваться переустановка операционной системы. Корпорация Майкрософт не может гарантировать, что эти проблемы удастся решить. Вносите изменения в реестр на ваш страх и риск.

    1. Получите идентификатор класса (CLSID) объекта COM. CLSID — это 128-битовое число, которое считается глобальным уникальным идентификатором (GUID), который используется для уникальной идентификации компонента, модуля или файла, содержащего этот COM-объект. При создании COM-объектов с помощью хранимых процедур OLE Automation первым параметром хранимой процедуры является программный идентификатор, или progID объекта OLE используется для получения CLSID. Эта символьная строка описывает класс объекта OLE и имеет следующую форму:

      OLEComponent.Object
      
    2. С помощью программного идентификатора можно найти идентификатор класса для COM-объекта.

      Откройте Редактор реестра (regedit.exe) и в HKEY_CLASSES_ROOT разделе используйте Find метод , чтобы найти ключ с именем <OLEComponent.Object>. Вы найдете его на других уровнях, но он должен находиться на уровне непосредственно под HKEY_CLASSES_ROOT. Найдя ключ, разверните папку с именем ключа, и вы увидите подраздел CLSID. Выберите папку, чтобы просмотреть значения в этом ключе. В правой части экрана находится заголовок с именем Default. Данные для этого ключа должны быть в следующей форме:

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

      Запишите это значение или скопируйте его в Блокнот. Добавьте скобки.

    3. Перейдите под HKEY_CLASSES_ROOT\CLSID ключ и найдите подраздел с этим номером GUID. После выделения HKEY_CLASSES_ROOT\CLSID ключа можно использовать функцию Найти в реестре Редактор (в меню Правка) и вставить GUID в диалоговое окно Поиск. Убедитесь, что вы нашли правильный интерфейс, проверив подраздел InprocServer32 под этим ключом, который указывает на расположение файла COM DLL. Если есть ключ TypeLib, проверка это значение GUID. Это должно отличаться от того, что было указано на шаге 1. В противном случае у вас есть идентификатор GUID TypeLib, а не GUID для объекта COM. Подраздел ProgID будет иметь значение OLEComponent.Object.1. Конечная версия используется только для этого примера и используется для управления версиями.

    4. В подразделе InprocServer32 идентификатора GUID убедитесь, что ThreadingModel значение существует и для него задано значение Оба или Бесплатный, чтобы убедиться, что маршалинг понимает потоковую модель объекта COM, чтобы обеспечить выполнение COM из SQL Server пространства процесса. Если значение отсутствует ThreadingModel или для него задано значение Apartment, создание экземпляра COM-объекта может быть несовместимым.

      Примечание.

      Если вы добавите ThreadingModel значение, убедитесь, что вы протестировали com-объект перед реализацией.

    5. Выделите номер ИЛИ подраздел GUID под ключом HKEY_CLASSES_ROOT\CLSID . В меню Правка выберите Создать, а затем — Строковое значение. В столбце Имя введите AppID.

    6. Нажмите клавишу ВВОД , а затем вставьте идентификатор класса или идентификатор GUID, который вы записали на шаге 1 в качестве значения. Идентификатор GUID должен находиться в фигурных скобках, как показано в следующем примере:

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

      Идентификатор приложения AppID используется DCOM для связывания библиотеки DLL с исполняемым файлом.

    7. Добавьте новый подраздел в и HKEY_CLASSES_ROOT\AppID задайте для его имени тот же идентификатор класса или номер GUID с скобками, как было вставлено на предыдущем шаге.

    8. Выделите имя GUID. В меню Правка выберите Создать, а затем — Строковое значение. В столбце Имя введите dllSurrogate.

      Оставьте столбец Данные пустым для этого значения. Так как столбец данных пуст, DCOM отправляет сообщение о запуске исполняемого файла по умолчанию dllhost.exeи загрузке COM-объекта в пространстве процесса.

    9. Закройте редактор реестра. В меню Пуск выберите пункт Выполнить. В диалоговом окне Выполнить введите DCOMCNFG.

      Нажмите клавишу ВВОД , чтобы открыть диалоговое окно Свойства распределенной конфигурации COM . Перейдите на вкладку Свойства по умолчанию и убедитесь, что выбран параметр Включить распределенную COM на этом компьютере. Если это не так, выберите его и нажмите кнопку Применить.

    10. Убедитесь, что учетная запись пользователя Windows NT, в котором выполняется SQL Server, имеет разрешение На полный доступ к разделам реестра для этого объекта. Если разрешений недостаточно или разделы реестра введены неправильно, при создании com-объекта могут возникнуть следующие ошибки:

      Сведения об ошибке ole automation
      HRESULT: 0x80040154
      Источник: расширенная процедура ODSOLE
      Описание: класс не зарегистрирован

      Сведения об ошибке ole automation
      HRESULT: 0x80070005
      Источник: расширенная процедура ODSOLE
      Описание. Доступ запрещен.

      Сведения об ошибке ole automation
      HRESULT: 0x80080005
      Источник: расширенная процедура ODSOLE
      Описание: сбой выполнения сервера

    11. Проверьте, выполняется ли файл 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 PID. Повторно запустите tlist.exe и передайте PID в качестве параметра. Здесь показаны библиотеки DLL, которые загружаются в dllhost.exe пространстве процесса. Com-объект на основе БИБЛИОТЕКи DLL должен быть указан как запущенный в этом процессе. После возврата скрипта повторное выполнение tlist.exe показывает, что dllhost.exe процесс больше не выполняется.

      В следующем примере выходных данных ADODB. Объект connection создается за пределами SQL Server пространства процесса. Это snapshot с помощью 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
      

Ссылки

Хранимые процедуры OLE Automation (Transact-SQL)