Quelle est la méthode propre pour éviter le TDispatchSilencer dans un EventSink
Bonjour,
J'ajoute un ActiveX d'inter-opérabilité dans l'application !
Cet ActiveX doit être interchangeable, aujourd'hui, une application Delphi lance l'ActiveX qui pourra ouvrir un WebService SOAP ou REST, un Server TCP\IP ou que sais-je encore ?!
On souhaite ouvrir à l'extérieur (pour du PHP), un lot de fonction "noyau" de l'application, pour le moment, seules deux méthodes devraient être ouvertes !
Ces fonctions sont massives (et personne ne sait vraiment ce que cela fait)
Je ne serais plus dans la boite quand l'on utilisera cet objet en prod ! D'où l'idée saugrenue d'ouvrir ces fonctions à l'extérieur pour ne plus coder en Delphi certains modules mais en PHP
En fait, j'utilise le Système d'Evènement de la Couche COM comme dans le Tutoriel de Laurent Dardenne pour "rétro-implémenter" les deux fonctions magiques dans l'Application Delphi, pour que l'Active recevant une commande puisse appeler la fonction comme un event (avec paramètre bien sur)
Cela fonctionne plutôt bien sauf pour la remonter les erreurs HResult du SafeCall !
Ces erreurs ne remontent pas !!!
Dommage, moi qui gérait DISP_E_NONAMEDARGS, DISP_E_BADPARAMCOUNT, E_INVALIDARG... plus d'autre Exception Interne !
En fait, c'est plus un délire architecturel qu'autre chose ! Mais ça me fait plaisir !
Les Evènements, je ne les codes pas en dispinterface d'habitude, je fais mon propre Connect(EventIntf) et c'est plus facile, mais comme le système existe en standard autant l'essayer !
Voici ce que j'ai fait dans la partie Implementation de l'Objet COM (la DLL)
Je n'utilise pas le Gestionnaire d'evènement standard EventConnect hérité de TAutoObject, je rédéfini le mien HandlerConnectionPointEventConnect
C'est cool que cela soit ouvert !
Code:
1 2 3 4 5
| type
TCensureInterOp = class(TAutoObject, IConnectionPointContainer, ICensureIInterOp)
private
...
procedure HandlerConnectionPointEventConnect(const Sink: IUnknown; Connecting: Boolean); // C'est un Evènement passé directement dans Initialize |
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
{* ----------------------------------------------------------------------------}
procedure TCensureInterOp.HandlerConnectionPointEventConnect(const Sink: IUnknown;
Connecting: Boolean);
var
varEventSink: IUnknown;
begin
if Connecting then
begin
// Dézingage de TDispatchSilencer
OleCheck(Sink.QueryInterface(AutoFactory.EventIID, varEventSink));
EventSink := varEventSink;
EventSinkChanged(EventSink);
end
else
begin
EventSink := nil;
EventSinkChanged(nil);
end;
end; |
Noté de HandlerConnectionPointEventConnect à la place du EventConnect généré automatiquement lorsque l'on coche ‘Générer le code de support d'événement'
Code:
1 2 3 4 5 6 7 8 9 10
| {* ----------------------------------------------------------------------------}
procedure TCensureInterOp.Initialize;
begin
inherited Initialize;
FConnectionPoints := TConnectionPoints.Create(Self);
if AutoFactory.EventTypeInfo <> nil then
FConnectionPoint := FConnectionPoints.CreateConnectionPoint(
AutoFactory.EventIID, ckSingle, HandlerConnectionPointEventConnect)
else FConnectionPoint := nil;
end; |
En retirant le TDispatchSilencer avec cette méthode, j'ai mes messages d'erreur via DISP_E_EXCEPTION dans ExcepInfo !
Au moins, je sais quand il y a une erreur !
C'est vilain ! non ?
Existe-t-il une méthode plus "simple" ?