Cet article présente le projet Delphi "TypeLibReader". Ce projet est un lecteur de bibliothèque de type.
Quelques fonctionnalités supplémentaires sont inclues avec un mini débuger permettant de scrupter et scripter les objets Automation.
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 comme 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 object Automation est scriptable (javascript ou vbscript) via le composant TSMScriptExecutor de Mike Shkolnik. Le (ou les) objet(s) crée(s), l'état de l'inspecteur d'objets,
le script et les options en cours peuvent être sauvegardés dans un projet Automation.
1.1. 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
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 leur flags, doc et dispid) de l'interface
"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 selection vers le presse-papier" : export du texte de la selection
Liste des dernières bibliothèques de type ouvertes (MRU).
2. 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'objet s'affiche. L'inspecteur d'objet est composé de trois onglets :
"Prop. Lecture"
: propriété en lecture
, dernière valeur lue
"Prop. Ecriture" : propriété en écriture, dernière valeur fixée
"Script" : Liste de objets disponibles, code source du script, panneau de commande, erreurs de script.
2.1. 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ée
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.
2.2. Inspecteur
Pour les coClass instanciées (en rouge), le menu contextuel "Evaluer"/"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 type 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 est inscrite
dans l'onglet "Prop. Lecture/Ecriture" de l'inspecteur d'objet. 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
ou le type (interface) de cette propriété est compatible Automation).
2.3. 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 recencé le nom des coClass instanciées (en rouge). Ces différents objets peuvent être
utiliser 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.
2.4. 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..).
A 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.
3. 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".
A 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 par la disponibilité d'un objet instancié. Dans le cas ou 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).
4. Améliorations possibles
Création dynamique : Le chargement de certaine bibliothèque de type volumineuse 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 noeud possède un pointer ITypeInfo le représentant. Cette construction
dynamique correspond "à un cablage" de l'événement "expand" sur les méthodes "GetMembers"... Il serait intéressant de reprendre
la partie sauvegarde (dans un projet Automation) des noeuds en lecture/écriture afin de permettre la construction dynamique au chargement
d'un projet mais aussi pour le chargement initial (fichier, registres, ROT).
Multi bibliothèque de type: L'intérêt principal d'un fonctionnement Multi-fenetré/Multi bibliothèque de type est de pouvoir inspecter/scripter des objets provenants
de plusieurs bibliothèque de type (par exemple: shdocvw.dll et mshtml.tlb).
Les fonctions héritées ne sont pas hierarchisées via l'interface héritée.
Les fonctions d'une interface ne sont pas présentées d'une façon hiérarchisé (cf. Microsoft OleView).
EDI de Script : actuellement les fonctionnalités de formatage et d'autocompletion 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).
5. Téléchargement et description des sources du projet
Le source du projet est composé d'un groupe de projet "Groupe de projet Debugeur 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ébuger 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é.
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 Debugeur et COMs.bpg : groupe de projet
TypeLibReader.exe : lecteur de bibliothèque de type
uTestTypeLib.pas : fiche principale du lecteur/débuger
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