La boîte à Tutoriels de Christopher PECAUD

Accéder à WMI sous Delphi
Laisser un commentaire

SOMMAIRE

I Introduction
II Accéder à WMI avec Delphi
IIII Effectuer une requête WMI
IV Conclusion

I Introduction

Nous allons voir dans ce tutoriel comment accéder à WMI à partir de Delphi. Vous pourrez donc utiliser des requêtes pour obtenir des informations concernant des périphériques sur votre réseau y compris les imprimantes. Nous allons détailler en détails la procédure à suivre et nous allons prendre un exemple simple : lister les imprimantes installer sur votre ordinateur. A la fin de ce tutoriel vous serez en mesure d’utiliser WMI dans vos futurs projets pour obtenir d’autres types d’informations.

II Accéder à WMI avec Delphi

La procédure est quelque peu différente par rapport à celle utilisée pour les langages de la plateforme .Net. En effet avec Delphi il n’est pas question de créer des instances d’objets préconçus comme ManagementScope, et ManagementObjectSearcher et ManagementObjectCollection… En effet il va falloir passer par les objets et fonctions da la bibliothèque ComObj. Nous aurons aussi besoin d’accéder à certaines routines de la bibliothèque ActiveX. Donc dans la section uses, il faut rajouter la ligne suivante :

Uses …, ComObj, ActiveX, … ;

Pour créer notre objet WMI, nous avons besoin de créer une méthode qui nous permet de réaliser cette opération en utilisant principalement la fonction OleCheck de la bibliothèque importée précédemment.

Nous allons nommer cette fonction GetWMIObject.

Dans un premier temps nous allons créer les variables locales nécessaires :

var chEaten : Integer;
    BindCtx : IBindCtx;
    Moniker : IMoniker;

OleCheck permet d’accéder et d’envelopper diverses routines COM. Nous allons l’utiliser conjointement avec des fonctions de la bibliothèque ActiveX. Nous allons utiliser dans un premier temps la méthode CreateBindCtx qui va nous retourner un pointeur vers une implémentation de IBindCtx qui est un objet de contexte de liaison. Nous utilisons ensuite la méthode MkParseDisplayName qui convertit la chaine de caractère qu’on lui envoie en argument en un objet système. Nous lui envoyons la chaîne suivante en argument : ‘winmgmts:\\.\root\CIMV2’. Celle-ci nous renvoie un pointeur vers un objet de type Moniker. Nous appelons pour finir la méthode BindToObject de l’objet Moniker. Celle-ci nous permet d’effectuer la liaison avec l’objet demandé. Ensuite elle s’assure du déclenchement de l’opération c’est-à-dire de l’exécution de l’objet si nécessaire, mais surtout elle nous fournit une interface de type IDispatch sur l’objet.

Voici le corps complet de cette fonction :

function GetWMIObject(const ObjectName : String) :IDispatch;
var chEaten : Integer;
    BindCtx : IBindCtx;
    Moniker : IMoniker;

begin
OleCheck(CreateBindCtx(0, BindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
OleCheck((Moniker.BindToObject(BindCtx, nil, IDispatch, result)));
end;

III Effectuer une requête WMI

Maintenant que nous avons créé notre fonction d’accès à notre objet nous pouvons créer une requête nous permettant de lister les imprimantes installées sur un ordinateur.

Nous allons, pour ce faire, créer une nouvelle fonction qui va nous permettre de réaliser une requête et d’exploiter le résultat retourné…

Donc dans un premier temps nous allons définir des variables locales :

 var objWMIService : OleVariant;
    colItems : OleVariant;
    colItem  : OleVariant;
    oEnum : IEnumVARIANT;
    iValue : LongWord;

La variable objWMIService nous permet de créer une instance d’objet à partir de la fonction que l’on a créé précédemment. Les variables colItems, et colItem sont utilisées pour exploiter les résultats de la requête. Nous envoyons en argument de la fonction execQuery de l’objet objWMIService la requête à effectuer, qui est dans notre cas : 'SELECT * FROM win32_printer'. La fonction nous renvoie une liste d’éléments qui nous permet d’initialiser notre objet collection colItems. Il nous faut ensuite balayer cette liste d’éléments. colItems et colItem étant de type OleVariant. Nous devons faire un cast de type. Pour énumérer des valeurs contenues dans un objet de type OleVariant, nous devons le convertir en objet IEnumVariant. Ceci est réalisé par la ligne de code suivante :

oEnum := IUnknown(colItems._NewEnum) as IEnumVariant;

Ensuite on peut énumérer chaque enregistrement de ce résultat par l’intermédiaire d’une boucle:

 while OEnum.next(1, colItem, iValue) = 0 do
     begin

       Form1.cbxPrinterName.Items.Add(colItem.Properties_.Item(wmiProperty, 0));
     end;

Dans cet exemple nous ajoutons chaque nom d’imprimante dans un contrôle de type Combobox. Pour ce faire nous utilisons la fonction next de l’interface INumVariant qui permet de balayer tous les objets contenus dans colItems. Cette fonction prend en argument le nombre d’éléments devant être traités, colItem étant un tableau contenant les valeurs de retour. Nous voulons ensuite juste les valeurs de chaque objet retourné correspondant à la propriété « Name ». En effet on veut juste retourner les noms des imprimantes installées sur un ordinateur. Ce qui est fait en utilisant la propriété Item de la propriété Properties_ de cet objet. Il faut lui envoyer en argument le nom de la propriété voulue, en l’occurrence c’est « Name ».

Voilà nous savons maintenant comment accéder à WMI à partir du Pascal Objet sous Delphi.

IV Conclusion

Nous avons vu qu’il «était possible également d’accéder à WMI via Delphi. Même si l’approche est un peu différente de celle utilisée avec le framework .Net ceci est malgré tout réalisable. Cela semble plus complexe au premier abord, mais maintenant que la méthode d’accès est connue, il vous sera plus facile de réaliser des requêtes plus complexes.