I. Présentation générale▲
Ce projet Delphi permet de visualiser le contenu d'une bibliothèque de type (Type Library).
La source de cette bibliothèque peut-être :
- un fichier par exemple shdocvw.dll, mshtml.tlb, msscript.ocx… ;
- le choix dans les registres d'une bibliothèque enregistrée :
- le choix dans la ROT (Running Object Table) d'un objet enregistré :
La lecture de la bibliothèque de type présente les informations de façon structurée. Il est possible de personnaliser l'affichage.
Le projet « TypeLibReader » permet d'inspecter ou de modifier une propriété (type OLE non scalaire) de l'interface d'une CoClass supportant l'Automation (IDispatch). Cet objet Automation est scriptable (JavaScript ou vbscript) via le composant TSMScriptExecutor de Mike Shkolnik. Le (ou les) objet(s) créé(s), l'état de l'inspecteur d'objets, le script et les options en cours peuvent être sauvegardés dans un projet Automation.
I-A. Lecture d'une bibliothèque de type et informations présentées▲
Les informations contenues dans la bibliothèque de type sont présentées dans quatre onglets distincts :
- Interface ;
- dispInterface ou Interface dispatchable ;
- CoClass ;
- Structures et constantes.
Dans chaque onglet sont présentées les informations suivantes :
Onglet |
Informations |
Exemple |
---|---|---|
« Interface » |
interface (non DUAL et non AUTOMATION), son GUI, l'héritage, les flags, la doc |
IXMLDocument2 ['{2B8DE2FE-8D2D-11D1-B2FC-00C04FD915A9}'] = interface(IDispatch) #FHIDDEN# #FDISPATCHABLE# |
« dispInterface » |
interface DUAL / AUTOMATION, son GUI, l'héritage, les flags d'interface, la doc. Les propriétés (prop. Read, prop. Write, prop Write Ref) et méthodes (avec leurs flags, doc et dispid) de l'interface |
IXMLDOMImplementation ['{2933BF8F-7B36-11D2-B20E-00C04F983E60}'] = dispinterface #FDUAL# #FNONEXTENSIBLE# #FDISPATCHABLE# |
« CoClass » |
coClass, son GUI, l'héritage, la doc. Chacune des interfaces héritées est représentée. |
DOMDocument ['{2933BF90-7B36-11D2-B20E-00C04F983E60}'] = CoClass(IXMLDOMDocument, XMLDOMDocumentEvents) « W3C-DOM XML Document » |
« TypeDef, Enum, Union » |
Alias : mappage et doc |
Alias DOMNodeType = tagDOMNodeType |
I-B. Options d'affichage et Outils divers▲
Les options d'affichage sont les suivantes :
- « Afficher méthodes IUnknown/IDispatch » : filtre des méthodes provenant des interfaces IUnknown ou Idispatch ;
- « Types de données Delphi » : affichage au format IDL (VT_xxx) ou type Delphi ;
- « Classement alphabétique ».
Quelques petits utilitaires sont implémentés :
- « Chercher » : recherche d'une chaine via l'API ItypeLib.FindName ;
- « Copier la sélection vers le presse-papier » : export du texte de la sélection ;
- Liste des dernières bibliothèques de type ouvertes (MRU).
II. Mise au point Automation▲
La fonctionnalité de mise au point (debug) ne s'applique qu'aux objets Automation (IDispatch). La coClass associée à l'objet instancié est affichée en rouge. Quand une coClass est instanciée, l'inspecteur d'objets s'affiche. L'inspecteur d'objets est composé de trois onglets :
- « Prop. Lecture » : propriété en lecture, dernière valeur lue ;
- « Prop. Écriture » : propriété en écriture, dernière valeur fixée ;
- « Script » : liste des objets disponibles, code source du script, panneau de commande, erreurs de script.
II-A. coClass : CoCreateInstance et ROT▲
Sur une coClass le menu contextuel « CoCreateInstance » permet d'instancier un objet. Par exemple après avoir chargé la bibliothèque de type d'Internet Explorer, il est possible d'instancier le navigateur (CoClass/InternetExplorer). L'objet ainsi créé est automatiquement ajouté à la liste des « objets disponibles » pour le script.
L'API « CoCreateInstance » utilise différentes options (CLSCTX_INPROC_SERVER, CLSCTX_INPROC_HANDLER, CLSCTX_LOCAL_SERVER) disponibles dans le menu « Options »/« Flags coCreateInstance ».
Le menu contextuel « ReleaseInstance » permet de libérer l'instance de la coClass.
Quand l'objet choisi dans la ROT supporte l'implémentation de IDispatch alors la coClass correspondante est affichée en rouge.
II-B. Inspecteur▲
Pour les coClass instanciées (en rouge), le menu contextuel « Évaluer »/« Modifier » permet de scrupter/modifier la valeur des propriétés (type OLE non scalaire) de l'interface par défaut (Automation).
Il y a deux types principaux de types de propriétés :
- les propriétés de types OLE (widestring, integer, IUnknown, Idispatch…) ;
- les propriétés de type utilisateur (interface).
Pour les types OLE (non scalaire), la propriété et sa valeur sont inscrites dans l'onglet « Prop. Lecture/Écriture » de l'inspecteur d'objets. Les propriétés dont l'interface est de type utilisateur sont automatiquement créées (via invoke) et le détail des membres de cette propriété est affiché pour inspection. Il est alors possible de scruter une propriété de la propriété (ceci infiniment dans la mesure où le type (interface) de cette propriété est compatible Automation).
II-C. Script▲
La fonctionnalité de script est implémentée via le moteur de script de Microsoft (MS ScriptControl) et le composant « TSMScriptExecutor » de Mike Shkolnik @ Scalabium.com.
Dans la liste des objets disponibles de l'onglet script est recensé le nom des coClass instanciées (en rouge). Ces différents objets peuvent être utilisés dans le script via ce nom. En option le programme propose le choix d'un langage de script : JavaScript ou vbscript.
Cette fonctionnalité de script est nécessaire pour scripter les propriétés dont le type est générique : IDispatch. Elle est aussi pratique pour automatiser les tests.
II-D. Projet Automation▲
Un projet Automation sauvegarde :
- le nom de la bibliothèque de type en cours ;
- la liste des objets instanciés ;
- les propriétés en lecture/écriture de ces objets ;
- différentes options (langage..).
À l'ouverture de ce fichier, la bibliothèque de type est affichée, les coClass instanciées et les différentes propriétés lues/écrites.
La sauvegarde dans un projet Automation permet de sauvegarder le contexte d'un test.
III. Problèmes connus - points faibles▲
- Dans ce projet le formatage dans le langage Delphi est très partiellement traité. Le programme traite la traduction des types OLE connus. Mais le principal problème du formatage Delphi réside dans la traduction du type de passage de paramètres (in/out, var, const).
- Propriété de propriété de type utilisateur (interface) : L'évaluation d'un membre d'une propriété de type utilisateur échoue. Cette question est posée sur le newsgroup activeX de Borland (cf. groups.google.com avec comme chaine : « INVOKE_PROPERTYGET IDispatch property succeeded but Result=nil ? »).
- Le nom de la bibliothèque de type de l'interface par défaut de la coclass choisie dans la ROT est lu dans les registres via la méthode « TRotObj.GetTypeLibFileNameWithIntfGuid ». À l'ouverture d'un projet Automation issu d'un objet choisi dans la ROT, le nom de la bibliothèque de type ouverte est fixé via cette méthode.
- L'interface ne vérifie pas la disponibilité d'un objet instancié. Dans le cas où celui-ci est détruit, il se produit des erreurs lors de l'inspection/script.
Une liste de « TODO : » est présente dans le projet via le menu Delphi : Voir (View) / Liste des TODO (To-Do List).
IV. Améliorations possibles▲
- Création dynamique : le chargement de certaines bibliothèques de type volumineuses est très long. La raison de cette lenteur est principalement expliquée par la lecture complète de la bibliothèque de type.
Une construction dynamique est possible, car chaque nœud possède un pointeur ITypeInfo le représentant. Cette construction dynamique correspond « à un câblage » de l'événement « expand » sur les méthodes « GetMembers »… Il serait intéressant de reprendre la partie sauvegarde (dans un projet Automation) des nœuds en lecture/écriture afin de permettre la construction dynamique au chargement d'un projet, mais aussi pour le chargement initial (fichier, registres, ROT). - Multibibliothèque de type: l'intérêt principal d'un fonctionnement Multifenêtré/Multibibliothèque de type est de pouvoir inspecter/scripter des objets provenant de plusieurs bibliothèques de type (par exemple: shdocvw.dll et mshtml.tlb).
- Les fonctions héritées ne sont pas hiérarchisées via l'interface héritée. Les fonctions d'une interface ne sont pas présentées d'une façon hiérarchisée (cf. Microsoft OleView).
- EDI de Script : actuellement les fonctionnalités de formatage et d'autocomplétion ne sont pas proposées. Cette carence est justifiée par la volonté de limiter le nombre de composants nécessaires à la compilation du projet. Ainsi les composants « SynEdit » ne sont pas inclus (à l'inverse de l'exemple de Mike Shkolnik accompagnant TSMScriptExecutor).
V. Téléchargement et description des sources du projet▲
Téléchargement du projet : TypeLibReader 1.42 Beta Src.zip
La source du projet est composée d'un groupe de projets « Groupe de projet Débogueur et COMs.bpg » qui contient deux projets.
-
Le premier projet « TypeLibReader.exe » correspond au programme principal. Ce projet est lui-même composé de deux composantes principales :
- Le lecteur/débogueur de bibliothèque de type (uTestTypeLib.pas, uTypeLibObj.pas, uFormChoiceRot.pas…) ;
- Un objet Automation interne (TTESTRotQueryCancel du type TAutoIntfObject dans uIQueryCancelAutoPlay.pas) qui s'enregistre dans la ROT et permet de tester le cas particulier des objets in-process non enregistrés.
- Le second projet « TestDebugAutomation.exe » correspond à un projet de serveur OLE Automation out-process (TTestDebugCA du type TAutoObjectROTDebug dans uTestDebugCA.pas) avec inscription dans la ROT.
Ces deux objets Automation (TAutoIntfObject et TAutoObject) sont disponibles pour tester et mettre au point les fonctionnalités de mise au point Automation (debug) du lecteur.
Description des différents fichiers pas du projet
-
Groupe de projet Débogueur et COMs.bpg : groupe de projets
-
TypeLibReader.exe : lecteur de bibliothèque de type
- uTestTypeLib.pas : fiche principale du lecteur/débogueur
- uFormChoiceRot.pas : fiche de choix d'un objet dans la ROT
- uTypeLibObj.pas : implémentation (via API et interfaces) des différentes fonctionnalités relatives aux bibliothèques de type (lecture…) et aux objets Automation (create, invoke…)
- uRotViewer.pas : implémentation de la lecture d'un élément dans la ROT
- TypeLibReader_TLB.pas : import Delphi de la bibliothèque de type des interfaces de test de l'objet TTESTRotQueryCancel
- uIQueryCancelAutoPlay.pas : définition de la classe TTESTRotQueryCancel implémentant l'interface système (XP) « IQueryCancelAutoPlay » et les interfaces de test Automation
- uFormTlbRegistry.pas : fiche de choix d'une bibliothèque de type dans le registre
- uConfig.pas : définition (via mappage XML) de la configuration (IXMLConfigType) du lecteur
- uProjetConfig.pas : définition (via mappage XML) de la configuration d'un projet Automation (IXMLProjetType)
-
TestDebugAutomation.exe : objet automation out-process pour test/ROT
- uTestDebugCA.pas : définition de la classe TTestDebugCA implémentant les interfaces de test
- TestDebugAutomation_TLB.pas : import Delphi de la bibliothèque de type des interfaces de test de l'objet TTestDebugCA
- uFormCOMAutomationTest.pas : fiche principale du serveur Automation out-process
- uTAutoObjectDebug.pas : implémentation des méthodes et des interfaces définies dans TestDebugAutomation_TLB
-
VI. Références▲
- Documentation Delphi : chapitre « OLE Programmer's Reference » (C:\Program Files\Fichiers communs\Borland Shared\MSHelp\OLE.HLP)
- MSDN API de lecture de bibliothèque de type
- COM Automation : Type Information, Partie (II) , Partie (III) des articles de Sean Baxter
- Delphi et ROT un article de gekko-software.nl
- Composant Delphi « TSMScriptExecutor » de Mike Shkolnik @ Scalabium
- Développement Delphi chez ChapsAndChips