Re: Interna einer Automations-App

Tech-Archive recommends: Fix windows errors by optimizing your registry

From: Martin Richter [MVP] (martin.richter_at_mvps.org)
Date: 03/07/05


Date: Mon, 07 Mar 2005 09:35:27 +0100

Hallo Andreas!

> ich habe mir die Frage gestellt, wie Word und Co. intern funktionieren.
> Wenn man VBA oder VBS nimmt, dann kann man über die Automation auf viele
> hierarchisch angeordnete COM-Objekte zugreifen. Nun glaube ich nicht,
> dass diese Apps intern CoCreateInstance für ihre eigenen Objekte
> aufrufen (z.B. mit einer angepassten Factory), oder etwa doch? Gibt es
> eine Möglichkeit, aus z.B. einer C++-Klassen-Instanz nachträglich ein
> COM-Objekt werden zu lassen, damit man es bei der Automatisierung
> zurückgeben kann?

Wenn Du eine Funktion hast, die einen Zeiger auf ein anderes Objekt
returniert, dann genügt es dieses Objekt einfach in Deiner
Prozessumgebung mitnew anzulegen und den entsprechenden Schnittstellen
Zeiger zu returnieren.

Der RPC-Proxy/Stub der Deine Funktion aufgerufen hat und nun einen
Zeiger zurückbekommt, muss nun selber (wenn nötig) wieder entsprechend
einen neuen Proxy/Stub erzeugen.

Du returnierst nur einfach einen IUnknown Zeiger oder was auch immer,
wie es in der IDL steht.

Ich habe dafür einige Templates die das erledigen:
template<class TB, class TI>
HRESULT CreateAGComObject(TI **ppVal)
{
  // Must be a valid pointer
  if (!ppVal)
   return E_POINTER;
  *ppVal = NULL;

  // Create this object
  CComObject<TB> *pObj = 0;
  HRESULT hr;
  hr = CComObject<TB>::CreateInstance(&pObj);
  if (SUCCEEDED(hr))
  {
   pObj->AddRef();
   if (SUCCEEDED(hr))
    hr = pObj->QueryInterface(__uuidof(TI),(void**)ppVal);
   pObj->Release();
  }
  return hr;
}

Und so sieht dann die Nutzung aus, wenn z.B. ein Enumerator erzeugt
werden muss. m_data sind einfach die Daten, mit denen der enumerator
initialisiert werden muss:

STDMETHODIMP CAGComForms::get__NewEnum(IUnknown** ppVal)
{
  AFX_MANAGE_STATE(AfxGetAppModuleState());
  VALIDATE_POINTER(ppVal);
  return CreateAGComObject<CAGComFormsEnumerator>(ppVal,m_data);
}

Nur als Hinweis: CComObject<Base>::CreateInstance ruft in keiner Weise
CoCreateInstance auf.

> Als zweites nun noch das: Kennt jemand den Pfad zur
> COM-Standard-Beschreibung? Ich wundere mich nämlich, wie das mit der
> vtable-Anordnung gemacht wird. Die Reihenfolge der Funktionen in IDL und
> in der C++-Klasse muss ja nicht übereinstimmen, und der C-Compiler weiß
> auch nichts von der IDL. Wie also machen dass z.B. Programmiersprachen,
> die C-Header nicht verarbeiten können und nur die Typelib zur Verfügung
> haben? Weichen die alle auf IDispatch aus? Es wäre mir allerdings nicht
> bekannt, dass z.B. Delphi nur duale Interfaces nutzen kann. Also wie
> geht das?

Wenn Du Dir die ATL Implementierung ansiehst, dann wird der
Interfacename direkt als Baisklasse angegeben. Damit ist die Reihenfolge
der Funktionen klar, oder?

Hier mal ein Beispiel aus einer meiner Applikationen. Es ist das Haupt
Objekt (Application), von dem alle anderen Objekte der Objekt Hierarchie
bezogen werden können:

class ATL_NO_VTABLE CAGComApplication :
        public CObject,
        public CComObjectRootEx<CComSingleThreadModel>,
        public CComCoClass<CAGComApplication, &AGCom::CLSID_AgvipApplication>,
        public IDispatchImpl<AGCom::Application, &AGCom::IID_Application,
&AGCom::LIBID_AGVIPLib, /*wMajor =*/ 1, /*wMinor =*/ 0>

Wie Du siehst wird in IDispatchImpl, AGCom::Application als Interface
angegeben. Die Beschreibung des Interface (also die Header Datei) wurde
durch meine IDL Datei vorgegeben und durch den MIDL erzeugt.

Ich empfehle Dir als Literatur: "Essential COM" von Don Box und "ATL
internals" Rectors und Sells

HTH

-- 
Martin Richter [MVP] WWJD
"In C we had to code our own bugs. In C++ we can inherit them."
FAQ : http://www.mpdvc.de
Samples: http://www.codeguru.com http://www.codeproject.com


Relevant Pages

  • Re: Problem marshalling interface pointer into local server
    ... I hope by main you mean the project for the shared IDL, ... Now that would be correct - an Automation-compatible interface ... Further to this, I had an issue where I have a in-proc server, ... Both servers implements IFace and register their ...
    (microsoft.public.vc.atl)
  • Re: Creating multiple instances of objects
    ... declared as an attribute in your IDL hptDBdata interface, ... The compiler may have been confused and failed to ... If you simply want to expose a database schema to the client, ...
    (comp.object.corba)
  • Re: How to? COM class library Property pass-by-reference for TypeLib [propput] ?
    ... I think Nicholas misunderstood your problem. ... trying to EXPORT a .NET class as a COM interface to emulate an older VB6 ... What I had to do is manually create my own IDL and my own TLB and, ... calling regasm /tlb, swap out the regasm-generated TLB with my homebrew TLB. ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Creating events in VC++ / ATL, receiving in VB
    ... What do you think is wrong with the IDL? ... library MYOWNLib ... different project where I have another class to implement the interface. ... Any ideas where I could have forgot about the connection? ...
    (microsoft.public.vb.com)
  • Re: Qndert_der_Win-Loader_meinen_Code=3F?=
    ... > dass COM da eine Serialisierung der Aufrufe über Window-Messages ... einem anderen STA Thread erzeugt wurde. ... Du kannst eben nicht einfach den IUnknown Zeiger nehmen, ... Wie bekommst Du also ein Interface in einen anderen Thread. ...
    (microsoft.public.de.vc)