Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Хотя суррогат, предоставляемый системой, будет более чем достаточно для большинства ситуаций, есть некоторые случаи, когда написание пользовательского суррогата может быть стоит. Ниже приводятся некоторые примеры.
- Пользовательский суррогат может обеспечить некоторые оптимизации или семантику, не присутствующих в суррогатной системе.
- Если библиотека DLL в процессе содержит код, который зависит от того, что находится в том же процессе, что и клиент, сервер DLL не будет работать правильно, если он работает в системе суррогат. Пользовательский суррогат может быть адаптирован к определенной библиотеке DLL для решения этой проблемы.
- Суррогат системы поддерживает модель смешанного потока, чтобы она могли загружать как бесплатные, так и библиотеки DLL моделей квартир. Настраиваемый суррогат может быть адаптирован для загрузки только библиотек DLL квартиры по соображениям эффективности или принять аргумент командной строки для типа БИБЛИОТЕК DLL, который разрешено загрузить.
- Пользовательский суррогат может принимать дополнительные параметры командной строки, которые система суррогат не выполняет.
- Системный суррогат вызывает CoInitializeSecurity и сообщает ему использовать все существующие параметры безопасности, найденные в разделе AppID в реестре. Пользовательский суррогат может использовать другой контекст безопасности.
- Интерфейсы, которые не являются ремотируемыми (например, для последних OCX) не будут работать с суррогатной системой. Пользовательский суррогат может упаковать интерфейсы БИБЛИОТЕКи DLL с собственной реализацией и использовать библиотеки DLL прокси-сервера или заглушки с определением remotable IDL, которое позволит удаленному интерфейсу.
Основной суррогатный поток обычно должен выполнять следующие действия по настройке:
- Вызовите CoInitializeEx , чтобы инициализировать поток и задать модель потоков.
- Если вы хотите, чтобы серверы DLL, выполняемые на сервере, могли использовать параметры безопасности в разделе реестра AppID , вызовите CoInitializeSecurity с возможностью EOAC_APPID. В противном случае будут использоваться устаревшие параметры безопасности.
- Вызовите CoRegisterSurrogate , чтобы зарегистрировать суррогатный интерфейс в COM.
- Вызовите ISurrogate::LoadDllServer для запрошенного CLSID.
- Поместите основной поток в цикл, чтобы периодически вызывать CoFreeUnusedLibraries.
- Когда COM вызывает ISurrogate::FreeSurrogate, отмените все фабрики классов и выход.
Суррогатный процесс должен реализовать интерфейс ISurrogate. Этот интерфейс следует зарегистрировать при запуске нового суррогата и после вызова CoInitializeEx. Как указано на предыдущих шагах, интерфейс ISurrogate имеет два метода, вызывающие COM: LoadDllServer, для динамической загрузки новых dll-серверов в существующие суррогаты; и FreeSurrogate для освобождения суррогата.
Реализация LoadDllServer, которая вызывает COM с запросом нагрузки, должна сначала создать объект фабрики классов, поддерживающий IUnknown, IClassFactory и IMarshal, а затем вызвать CoRegisterClassObject, чтобы зарегистрировать объект в качестве фабрики классов для запрошенного CLSID.
Фабрика классов, зарегистрированная суррогатным процессом, не является фактической фабрикой классов, реализованной сервером DLL, но является фабрикой универсальных классов, реализованной суррогатным процессом, поддерживающим IClassFactory и IMarshal. Так как это фабрика классов суррогата, а не сервер DLL, зарегистрированный, фабрика классов суррогата должна будет использовать фабрику реальных классов для создания экземпляра объекта для зарегистрированного CLSID. Суррогат IClassFactory::CreateInstance должен выглядеть примерно так:
STDMETHODIMP CSurrogateFactory::CreateInstance(
IUnknown* pUnkOuter,
REFIID iid,
void** ppv)
{
void* pcf;
HRESULT hr;
hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, IID_IClassFactory, &pcf);
if ( FAILED(hr) )
return hr;
hr = ((IClassFactory*)pcf)->CreateInstance(pUnkOuter, iid, ppv);
((IClassFactory*)pcf)->Release();
return hr;
}
Фабрика классов суррогата также должна поддерживать IMarshal, так как вызов CoGetClassObject может запрашивать любой интерфейс из зарегистрированной фабрики классов, а не только IClassFactory. Кроме того, так как фабрика универсальных классов поддерживает только IUnknown и IClassFactory, запросы для других интерфейсов должны направляться в реальный объект. Таким образом, должен быть метод MarshalInterface , который должен быть похож на следующий:
STDMETHODIMP CSurrogateFactory::MarshalInterface(
IStream *pStm,
REFIID riid, void *pv,
WORD dwDestContext,
void *pvDestContext,
DWORD mshlflags )
{
void * pCF = NULL;
HRESULT hr;
hr = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER, NULL, riid, &pCF);
if ( FAILED(hr) )
return hr;
hr = CoMarshalInterface(pStm, riid, (IUnknown*)pCF, dwDestContext, pvDestContext, mshlflags);
((IUnknown*)pCF)->Release();
return S_OK;
Суррогат, на котором размещается сервер DLL, должен публиковать объекты класса DLL-сервера с вызовом CoRegisterClassObject. Все фабрики классов для суррогатов DLL должны быть зарегистрированы как REGCLS_SURROGATE. REGCLS_SINGLUSE и REGCLS_MULTIPLEUSE не следует использовать для серверов DLL, загруженных в суррогаты.
Следуя этим рекомендациям по созданию суррогатного процесса, если это необходимо сделать, должно обеспечить надлежащее поведение.
См. также