Schreiben eines benutzerdefinierten Ersatzzeichens
Obwohl das vom System bereitgestellte Ersatzzeichen in den meisten Situationen mehr als ausreichend ist, kann es in einigen Fällen sinnvoll sein, ein benutzerdefiniertes Ersatzzeichen zu schreiben. Nachstehend sind einige Beispiele aufgeführt:
- Ein benutzerdefiniertes Ersatzzeichen kann einige Optimierungen oder Semantik bereitstellen, die im System-Ersatzzeichen nicht vorhanden sind.
- Wenn eine Prozess-DLL Code enthält, der davon abhängt, dass er sich im selben Prozess wie der Client befindet, funktioniert der DLL-Server nicht ordnungsgemäß, wenn er im Systemsyntgaten ausgeführt wird. Ein benutzerdefiniertes Ersatzzeichen kann auf eine bestimmte DLL zugeschnitten werden, um dies zu behandeln.
- Das System-Ersatzzeichen unterstützt ein Mixed-Threading-Modell, sodass es sowohl Free- als auch Apartmentmodell-DLLs laden kann. Ein benutzerdefiniertes Ersatzzeichen kann aus Effizienzgründen so angepasst werden, dass nur Apartment-DLLs geladen werden, oder um ein Befehlszeilenargument für den Dll-Typ zu akzeptieren, der geladen werden darf.
- Ein benutzerdefiniertes Ersatzzeichen könnte zusätzliche Befehlszeilenparameter verwenden, die das Systemsyntgate nicht verwendet.
- Das System-Ersatzzeichen ruft CoInitializeSecurity auf und weist es an, alle vorhandenen Sicherheitseinstellungen zu verwenden, die unter dem AppID-Schlüssel in der Registrierung gefunden werden. Ein benutzerdefiniertes Ersatzzeichen kann einen anderen Sicherheitskontext verwenden.
- Schnittstellen, die nicht remotable sind (z. B. für aktuelle OCX-Dateien), funktionieren nicht mit dem System-Ersatzzeichen. Ein benutzerdefiniertes Ersatzzeichen könnte die Schnittstellen der DLL mit einer eigenen Implementierung umschließen und Proxy-/Stub-DLLs mit einer remotablen IDL-Definition verwenden, die das Remoteieren der Schnittstelle ermöglicht.
Der Hauptthread für Ersatzzeichen sollte in der Regel die folgenden Setupschritte ausführen:
- Rufen Sie CoInitializeEx auf, um den Thread zu initialisieren und das Threadingmodell festlegen.
- Wenn sie möchten, dass die DLL-Server, die auf dem Server ausgeführt werden, die Sicherheitseinstellungen im AppID-Registrierungsschlüssel verwenden können, rufen Sie CoInitializeSecurity mit der EOAC-APPID-Funktion _ auf. Andernfalls werden legacy-Sicherheitseinstellungen verwendet.
- Rufen Sie CoRegisterSurrogate auf, um die Ersatzschnittstelle bei COM zu registrieren.
- Rufen Sie ISurrogate::LoadDllServer für die angeforderte CLSID auf.
- Setzen Sie den Hauptthread in eine Schleife, um in regelmäßigen Abständen CoFreeUnusedLibraries auf aufruft.
- Wenn COM ISurrogate::FreeSurrogateaufruft, widerrufen Sie alle Klassen factorys und beenden.
Ein Ersatzprozess muss die ISurrogate-Schnittstelle implementieren. Diese Schnittstelle sollte registriert werden, wenn ein neues Ersatzzeichen gestartet wird und nach dem Aufruf von CoInitializeEx. Wie in den vorherigen Schritten angegeben, verfügt die ISurrogate-Schnittstelle über zwei Methoden, die COM aufruft: LoadDllServer, um neue DLL-Server dynamisch in vorhandene Ersatzzeichen zu laden. und FreeSurrogate, um das Ersatzzeichen frei zu geben.
Die Implementierung von LoadDllServer,die COM mit einer Ladeanforderung aufruft, muss zuerst ein Klassenfactoryobjekt erstellen, das IUnknown, IClassFactoryund IMarshalunterstützt, und dann CoRegisterClassObject aufrufen, um das Objekt als Klassenfactory für die angeforderte CLSID zu registrieren.
Die vom Ersatzzeichenprozess registrierte Klassenfactory ist nicht die tatsächliche Klassenfactory, die vom DLL-Server implementiert wird, sondern eine generische Klassenfactory, die durch den Ersatzprozess implementiert wird, der IClassFactory und IMarshal unterstützt. Da es sich um die Klassen factory des Ersatzzeichens handelt und nicht um die des DLL-Servers, der registriert wird, muss die Klassen factory des Ersatzzeichens die Realklassen-Factory verwenden, um eine Instanz des Objekts für die registrierte CLSID zu erstellen. Die IClassFactory::CreateInstance des Ersatzzeichens sollte in etwa wie im folgenden Beispiel aussehen:
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;
}
Die Klassenfactory des Ersatzzeichens muss auch IMarshal unterstützen, da ein Aufruf von CoGetClassObject eine beliebige Schnittstelle von der registrierten Klassenfactory anfordern kann, nicht nur von IClassFactory. Da die generische Klassenfactory nur IUnknown und IClassFactory unterstützt, müssen Anforderungen für andere Schnittstellen an das echte Objekt geleitet werden. Daher sollte eine MarshalInterface-Methode ähnlich der folgenden sein:
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;
Das Ersatzzeichen, das einen DLL-Server enthält, muss die Klassenobjekte des DLL-Servers mit einem Aufruf von CoRegisterClassObject veröffentlichen. Alle Klassen factorys für DLL-Ersatzzeichen sollten als REGCLS _ SURROGATE registriert werden. REGCLS SINGLUSE und REGCLS MULTIPLEUSE sollten nicht für DLL-Server verwendet werden, _ _ die in Ersatzzeichen geladen werden.
Die Einhaltung dieser Richtlinien zum Erstellen eines Ersatzzeichenprozesses, wenn dies erforderlich ist, sollte ein ordnungsgemäßes Verhalten sicherstellen.