Jump to content

DVBV Events und ConnectionPoint Unterstützung in COM


dbraner

Recommended Posts

Ich versuche gerade in C++ die COM-Events des DVBViewers anzuzapfen. Da ich die MFCs mit Visual Studio verwende, ist die Implementierung im Prinzip recht einfach. Leider komme ich an einer Stelle aber nicht weiter. Mein Client greift per ConnectionPoints auf den DVBViewer zu und legt einen EventSink an.

 

Dazu wird folgende Funktion per IUnknown Pointer auf DVBViewer aufgerufen:

 

IUnk->QueryInterface (IID_IConnectionPointContainer, ...)

 

Dieser Aufruf schlägt fehl, da der DVBViewer diese Schnittstelle anscheinend nicht unterstützt. Kann man dies implementieren? Mache ich was falsch? Gibt es eine andere Methode, per C++ an die Events ranzukommen?

 

Vielleicht könnte einer der Entwickler darauf antworten ...

Link to comment

Leider kann ich Dir da nicht wirklich weiterhelfen. Alle notwendigen Interfaces werden angeboten bzw. implementiert vom DVBViewer. Ich nutze ja genau das gleiche vom DVBViewer spy aus.

Link to comment
Ich versuche gerade in C++ die COM-Events des DVBViewers anzuzapfen. Da ich die MFCs mit Visual Studio verwende, ist die Implementierung im Prinzip recht einfach. Leider komme ich an einer Stelle aber nicht weiter. Mein Client greift per ConnectionPoints auf den DVBViewer zu und legt einen EventSink an.

 

Dazu wird folgende Funktion per IUnknown Pointer auf DVBViewer aufgerufen:

 

IUnk->QueryInterface (IID_IConnectionPointContainer, ...)

 

Dieser Aufruf schlägt fehl, da der DVBViewer diese Schnittstelle anscheinend nicht unterstützt. Kann man dies implementieren? Mache ich was falsch? Gibt es eine andere Methode, per C++ an die Events ranzukommen?

 

Vielleicht könnte einer der Entwickler darauf antworten ...

Kannst Du mal den vollständigen Beispielcode, der nicht geht, irgendwie anhängen. Espl. inkl. Erzeugen des IUnk, aber auch Datentyp et al. Der Teufel steckt vermutlich im Detail und die eine Zeile hilft für eine Analyse nicht wirklich.

 

Jochen

Link to comment
Leider kann ich Dir da nicht wirklich weiterhelfen. Alle notwendigen Interfaces werden angeboten bzw. implementiert vom DVBViewer. Ich nutze ja genau das gleiche vom DVBViewer spy aus.

 

Was genau ist denn der Unterschied zwischen den Interfaces IDVBViewerEvent und IDVBViewerEventhelper? In der COM Doku steht, dass die Property Event von IDVBViewer das Interface IDVBViewerEventhelper liefert. Bei der Erklärung von IDVBViewerEvents steht wiederum, dass dieses Interface ebenfalls über die Property Event abgrefragt werden kann. welches nun von den beiden, und was ist der Zweck?

Link to comment
Kannst Du mal den vollständigen Beispielcode, der nicht geht, irgendwie anhängen. Espl. inkl. Erzeugen des IUnk, aber auch Datentyp et al. Der Teufel steckt vermutlich im Detail und die eine Zeile hilft für eine Analyse nicht wirklich.

 

Jochen

 

Also hier mal mein MFC Beispielcode:

 

CLSID clsid;
IUnknown *pIUnknown;

CLSIDFromProgID (L"DVBViewerServer.DVBViewer", &clsid);

hr = GetActiveObject (clsid, NULL, &pIUnknown);

// Jetzt kommt das Problem
AfxConnectionAdvise (pIUnknown, IID_IDVBVEventSink, pUnkSink, FALSE, &dwCookie);

 

Wenn ich mit dem Debugger in die Funktion AfxConnectionAdvise reingehe, wird dort als erstes folgendes aufgerufen:

 

pIUnknown->QueryInterface (IID_IConnectionPointContainer, &pCPC);

 

Und dieser Aufruf schlägt fehl. pIUnknown ist gültig. Damit bekomme ich nämlich per Queryinterface auf IID_IDispatch einen funktionierenden Handle für DVBViewer, über das ich z.B. per SendCommand Befehle schicken kann.

 

Anzumerken ist noch, dass die Funktion AfxConnectionAdvise eine interne MFC Funktion ist. Habe ich mir also nicht ausgedacht. Mit MS-Word als COM-Server funktioniert das ganze übrigens ...

Edited by dbraner
Link to comment

Wenn ich die Diskussion in Deinem anderen Thread richtig verstanden habe, ist es auch nicht das Primärobject (DVBViewerServer.DVBViewer), das den Connection Point Container anbietet. Vielmehr musst Du von diesem das Events Object abfragen und dessen Interface als ersten Parameter beim Advise verwenden.

 

Jochen

Link to comment

Du machst kein queryinterface auf das hauptobjekt selber, sondern auf das IDVBViewerEventhelper interface, das Du Dir über IDVBViewer.Events holst , darauf kannst Du dann ein queryinterface auf das IConnectionPointContainer interface machen.

Ich musste da erstmal sehr tief in den delphi bibliotheken graben, da das hier alles automatisch angelegt wird...

Link to comment
Du machst kein queryinterface auf das hauptobjekt selber, sondern auf das IDVBViewerEventhelper interface, das Du Dir über IDVBViewer.Events holst , darauf kannst Du dann ein queryinterface auf das IConnectionPointContainer interface machen.

Ich musste da erstmal sehr tief in den delphi bibliotheken graben, da das hier alles automatisch angelegt wird...

 

Vielen Dank an Euch. Damit funktioniert die Abfrage des ConnectionPointContainers. Als nächstes wird nun für den Container die Funktion FindConnectionPoint() aufgerufen. Dabei wird eine IID übergeben. Ich hab nur keine Ahnung welche. In der Doku zur Funktion steht "Ein Verweis auf die IID der Ausgangsschnittstelle, deren Verbindungspunkt angefragt wird".

 

Welche IID ist gemeint? IID_IDVBViewer, IID_IEventHelper, ...?

 

Wenn ich das noch habe, müsste es eigentlich funktionieren.

Link to comment

So nach dem letzten Tipp von Lars läuft der Verbindungsaufbau in meinem Programm durch, d.h. die Funktion AfxConnectionAdvise findet zunächst den ConnectionpointContainer und danach auch einen ConnectionPoint. Nach der reinen Microsoft MFC Lehre müsste nun alles funktionieren, siehe auch

 

http://support.microsoft.com/default.aspx?...kb;en-us;181845

 

Bei MS-Word tut auch alles. Nur meine DVBViewer Eventroutinen werden leider trotzdem nicht aufgerufen ;)

 

Ich werde mal morgen einen etwas größeren Code-Ausschnitt posten. Vielleicht fällt ja jemandem der entscheindende Fehler auf. Ich hab so das Gefühl es passt fast alles und das ganze braucht nur noch einen Tritt ...

Link to comment

Hier nun der etwas auführlichere Code Ausschnitt. Ich bin vorgegangen wie in http://support.microsoft.com/default.aspx?...kb;en-us;181845 beschrieben, d.h. eine neue Klasse CDVBVEventSink abgeleitet von CCmdTarget angelegt, die die Events vom DVBViewer empfangen soll. Die Implementierung der Klasse sieht im wesentlichen so aus:

 

BEGIN_DISPATCH_MAP(CDVBVEventSink, CCmdTarget)
  DISP_FUNCTION_ID(CDVBVEventSink, "OnChannelChange", 0xc9, OnChannelChange, VT_EMPTY, VTS_I4)
  DISP_FUNCTION_ID(CDVBVEventSink, "OnAction", 0xd2, OnAction, VT_EMPTY, VTS_I4)
END_DISPATCH_MAP()

static const IID IID_IDVBVEventSink =
{ 0x017FD4A8, 0x5E00, 0x4DF8, { 0xA3, 0x88, 0x43, 0x4B, 0x8E, 0x59, 0x2C, 0xC4 } };

BEGIN_INTERFACE_MAP(CDVBVEventSink, CCmdTarget)
INTERFACE_PART(CDVBVEventSink, IID_IDVBVEventSink, Dispatch)
END_INTERFACE_MAP()

void CDVBVEventSink::OnAction (long ActionId)
{
  ::AfxMessageBox ("OnAction");
}

void CDVBVEventSink::OnChannelChange (long ChannelNo)
{
  ::AfxMessageBox ("OnChannelChange");
}

 

Hier bin ich am überlegen, ob die IID korrekt ist. In der MS-Doku heißt es, man soll die IID angeben, die vom COM OBject-Spy beim Typelib Eintrag des Servers (DVBViewer) angezeigt wird. Das ist eben die oben angegebene.

 

Im eigentlichen Programm wird dann die Verbindung zum DVBViewerEvent-Interface per Connectionpoints aufgebaut. Die Klasse DVBViewer ist eine Wrapper Klasse für das DVBViewer-Interface, die von Visualstudio automatisch erzeugt wurde und einem das Leben etwas erleichtert. Zusätzlich wird noch ein Object der EventSink-Klasse (s.o.) erzeugt:

 

CDVBViewer m_DVBViewer;
CDVBVEventSink m_DVBVEventSink;
DWORD m_dwCookie;

HRESULT hr;
CLSID clsid;

IUnknown *pIUnknown;
IDispatch *pIDispatch;

IID IID_IDVBViewerEvents = 
  { 0xB397FB16, 0xA027, 0x4D5B, { 0x88, 0xEB, 0xFD, 0x9A, 0x2A, 0xA2, 0x8D, 0x92 }};

CLSIDFromProgID (L"DVBViewerServer.DVBViewer", &clsid);

hr = GetActiveObject (clsid, NULL, &pIUnknown);
if (SUCCEEDED (hr))
{
  hr = pIUnknown->QueryInterface (IID_IDispatch, (void **) &pIDispatch);
  pIUnknown->Release ();

  if (SUCCEEDED (hr))
  {
  m_DVBViewer.AttachDispatch (pIDispatch);
  if (AfxConnectionAdvise (m_DVBViewer.get_Events (), IID_IDVBViewerEvents,
	 m_DVBVEventSink.GetIDispatch (FALSE), FALSE, &m_dwCookie))
	 ::AfxMessageBox ("Advise successful");
  else
	 ::AfxMessageBox ("Advise failed");
  }
  else
  ::AfxMessageBox ("Can't get DVBV IDispatch");
}
else
  ::AfxMessageBox ("Can't get DVBV IUnknown");

 

Dieser Code läuft fehlerfrei durch, d.h. die Verbindung zwischen meinem EventSink und dem DVBViewerEvent-Interface wird per Connectionpoint hergestellt. Der einzige Haken: Meine Eventhandler Funktionen werden niemals aufgerufen.

 

Fällt jemandem dazu was ein? Ist die ganz oben definierte IID korrekt?

Edited by dbraner
Link to comment
  • 2 weeks later...

So wie ich die Sache sehe, werden wir bzgl. Dvb script: funktioniert

PHP: funktioniert, aber im Browser nicht praktikabel anwendbar

Edited by dbraner
Link to comment

irgendwie funktioniert das posten hier nicht mehr. Das board zerstört meine posts :(

Edited by dbraner
Link to comment
  • 3 weeks later...
Dieser Code läuft fehlerfrei durch, d.h. die Verbindung zwischen meinem EventSink und dem DVBViewerEvent-Interface wird per Connectionpoint hergestellt. Der einzige Haken: Meine Eventhandler Funktionen werden niemals aufgerufen.

Fällt jemandem dazu was ein? Ist die ganz oben definierte IID korrekt?

 

Hallo, bin wieder zurück.

MFC ist nicht so mein Ding. Aber zum IDispatch-Interface gehört auch GetIDsOfNames. Hast Du dies mal aus-implementiert? Könnte mir vorstellen dass das DVBV/Delphi-Framework sich zuerst eine ID für OnChannelChange über GetIDsOfNames besorgt und mit dieser dann in das Invoke geht.

 

mfg erwin

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...