Egyedi helyettes készítése
Habár a rendszer által biztosított helyettesítés a legtöbb helyzetben több mint megfelelő, vannak olyan esetek, amikor érdemes lehet egyéni helyettesítést írni. Az alábbiakban néhány példát mutatunk be:
- Egy egyéni helyettesítő olyan optimalizálásokat vagy szemantikai elemeket biztosíthat, amelyek nincsenek jelen a rendszer helyettesítőjében.
- Ha egy processben lévő DLL olyan kódot tartalmaz, amely attól függ, hogy ugyanabban a folyamatban fut, mint az ügyfél, a DLL-kiszolgáló nem fog megfelelően működni, ha rendszer szurrogátos folyamataként fut. Az egyéni helyettesítők egy adott DLL-hez igazíthatók ennek kezeléséhez.
- A rendszer helyettesítő támogatja a vegyes szálú modellt, hogy betölthesse az ingyenes és a lakásmodell DLL-jeit is. Az egyéni helyetteseket úgy lehet testre szabni, hogy csak a lakás DLL-jeit töltse be hatékonysági okokból, vagy hogy elfogadjon egy parancssori argumentumot a betölthető DLL típusához.
- Az egyéni helyettesek olyan további parancssori paramétereket is igénybe vehetnek, amelyeket a rendszer helyettesítője nem.
- A rendszer helyettese meghívja CoInitializeSecurity, és közli vele, hogy használja az AppID kulcs alatt található meglévő biztonsági beállításokat a beállításjegyzékben. Az egyéni helyettes más biztonsági környezetet is használhat.
- A nem áthelyezhető felületek (például a legutóbbi OCX-ek esetében) nem működnek a rendszer helyettesítőivel. Az egyéni helyettesítők a DLL interfészeit a saját implementációjukkal burkolhatják, és proxy/csonk DLL-eket használhatnak egy távolról használható IDL-definícióval, amely lehetővé tenné a felület távoli elérését.
A fő helyettesítő szálnak általában a következő telepítési lépéseket kell végrehajtania:
- Hívja meg CoInitializeEx a szál inicializálásához és a szálmodell beállításához.
- Ha azt szeretné, hogy a kiszolgálón futó DLL-kiszolgálók használni tudják az AppID beállításkulcs biztonsági beállításait, hívja meg a CoInitializeSecurity a EOAC_APPID képességgel. Ellenkező esetben a rendszer régi biztonsági beállításokat használ.
- Hívja meg CoRegisterSurrogate, hogy regisztrálja a helyettesítő felületet a COM-ba.
- Hívja meg ISurrogate::LoadDllServer a kért CLSID-hez.
- Helyezze a főszálat egy olyan ciklusba, amely rendszeresen meghívja a CoFreeUnusedLibraries függvényt.
- Amikor a COM meghívja ISurrogate::FreeSurrogate, vonja vissza az összes osztálygyárat, és lépjen ki.
A helyettesítő folyamatnak implementálnia kell a ISurrogate felületet. Ezt a felületet új helyettes indításakor és CoInitializeExhívása után kell regisztrálni. Az előző lépésekben leírtaknak megfelelően az ISurrogate interfész két metódussal rendelkezik, amelyeket a COM meghív: LoadDllServer, hogy dinamikusan betöltse az új DLL-kiszolgálókat a meglévő helyettesítőkbe; és FreeSurrogate, hogy felszabadítsa a helyettesítőt.
Az LoadDllServerimplementációjának , amelyet a COM terheléskéréssel hív meg, először létre kell hoznia egy osztály-előállító objektumot, amely támogatja IUnknown, IClassFactoryés IMarshal, majd meghívja CoRegisterClassObject, hogy az objektumot osztály-előállítóként regisztrálja a kért CLSID-hez.
A helyettesítő folyamat által regisztrált osztály-előállító nem a DLL-kiszolgáló által implementált tényleges osztály-előállító, hanem a helyettesítő folyamat által implementált általános osztály-előállító, amely támogatja IClassFactory és IMarshal. Mivel ez a helyettesítő osztálygyár, nem pedig a regisztrálandó DLL-kiszolgálóé, a helyettesítő osztálygyárnak a valódi osztály-előállítót kell használnia az objektum példányának létrehozásához a regisztrált CLSID-hez. A helyettes IClassFactory::CreateInstance-nak az alábbi példára kell hasonlítania:
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;
}
A helyettes osztály gyár is támogatnia kell IMarshal, mert a hívás CoGetClassObject kérheti bármilyen interfész a regisztrált osztály gyár, nem csak IClassFactory. Továbbá, mivel az általános osztálygyár csak IUnknown és IClassFactorytámogat, a többi interfészre vonatkozó kéréseket a valódi objektumra kell irányítani. Ezért egy MarshalInterface metódusnak kell lennie, amelynek a következőhöz hasonlónak kell lennie:
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;
A DLL-kiszolgálót futtató helyettesnek közzé kell tennie a DLL-kiszolgáló osztályobjektumát a CoRegisterClassObjecthívásával. A DLL-helyettesítők összes osztálygyárát REGCLS_SURROGATE-ként kell regisztrálni. REGCLS_SINGLUSE és REGCLS_MULTIPLEUSE nem használható helyettesítőkbe betöltött DLL-kiszolgálókhoz.
Ha szükséges, a megfelelő viselkedés biztosítása érdekében kövesse ezeket az irányelveket a helyettesítő folyamat létrehozásához.
Kapcsolódó témakörök