Megosztás a következőn keresztül:


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:

  1. Hívja meg CoInitializeEx a szál inicializálásához és a szálmodell beállításához.
  2. 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.
  3. Hívja meg CoRegisterSurrogate, hogy regisztrálja a helyettesítő felületet a COM-ba.
  4. Hívja meg ISurrogate::LoadDllServer a kért CLSID-hez.
  5. Helyezze a főszálat egy olyan ciklusba, amely rendszeresen meghívja a CoFreeUnusedLibraries függvényt.
  6. 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.

DLL-helyettesítők