FAQ DelphiConsultez toutes les FAQ
Nombre d'auteurs : 124, nombre de questions : 934, dernière mise à jour : 23 octobre 2024 Ajouter une question
Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums Delphi et Delphi et bases de données de www.developpez.com et de l'expérience personnelle des auteurs.
Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose soient correctes. Les auteurs font le maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous souhaitez y apporter des corrections ou la compléter, contactez un responsable (lien au bas de cette page).
Nous espérons que cette FAQ saura répondre à vos attentes. Nous vous en souhaitons une bonne lecture.
L'équipe Delphi de Developpez.com.
- Comment se connecter à WMI ?
- Qu'est-ce que l'objet SWbemObject ?
- Comment récupérer les éléments d'une collection de données WMI ?
- Comment énumérer les propriétés d'une instance SWbemObject ?
- Qu'est-ce qu'un qualificateur ?
- Comment afficher le chemin d'une instance ?
- Comment convertir une propriété en chaîne de caractères ?
- Comment retrouver toutes les instances d'une classe WMI ?
- Comment retrouver une instance partielle ?
- Comment retrouver une propriété sur une collection d'instances ?
- Comment appeler une méthode d'une instance WMI ?
- Comment modifier les privilèges afin d'effectuer un shutdown ?
Avant toute chose vous devez importer la librairie de type (fichier .TLB) qui se trouve dans le répertoire du référentiel WMI.
Code other : | Sélectionner tout |
1 2 3 | Sous XP : C:\WINDOWS\system32\wbem\wbemdisp.tlb C:\WINDOWS\system32\wbem\wbemads.tlb (Pour manipuler Active Directory via WMI) |
Une fois ceci fait vous disposerez d'une unité qui vous permettra d'accéder aux objets WMI. Cette unité se trouvera dans le répertoire ..\Delphi\Imports\xxxx_TLB.pas.
Cette unité est à ajouter systématiquement dans la clause uses pour tous les exemples concernant WMI présentés dans cette FAQ.
Pour se connecter à WMI on utilise un composant TSWbemLocator.
Sa méthode ConnectServer établit une connexion au référentiel WMI dans un espace de noms particulier. Dans l'exemple suivant on se connecte dans l'espace de noms ROOT\CIMV2.
La modification du curseur de la souris indique à l'utilisateur la phase de connexion au référentiel WMI.
L'utilisation du flag wbemConnectFlagUseMaxWait évite une attente indéfinie en cas d'indisponibilité de la machine distante.
Si l'appel de la méthode ConnectServer réussit, elle renvoie un objet SWbemServices initialisé, sinon le traitement ne peut se poursuivre.
Cet objet SWbemServices nous permettra d'exécuter des opérations sur l'espace de noms courant.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | Var WMILocator: TSWbemLocator; WmiService: SWbemServices; OldCursor: TCursor; begin WMILocator:= TSWbemLocator.Create(self); try OldCursor := Screen.Cursor; Screen.Cursor := crSQLWait; WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); Finally WMILocator.Free; Screen.Cursor:= OldCursor; end; end; |
Ce code ne contient pas de test d'erreurs. Vous trouverez dans les codes sources proposés avec le second tutoriel sur WMI le projet 1-SWbemLastError\WbemLastError.dpr qui vous permettra de voir dans le détail la gestion des erreurs.
Vous pouvez utiliser les méthodes et les propriétés d'un objet SWbemObject pour représenter une définition de classe WMI ou une instance d'objet de n'importe quelle classe WMI.
L'objet que vous manipulez est une copie locale. Si vous souhaitez modifier l'objet dans le référentiel WMI, utilisez sa méthode put_.
Si vous voulez créer une nouvelle classe, utilisez SWbemServices.Get avec un nom de path vide. L'appel retourne un objet SWbemObject qui peut devenir une classe.
Vous pouvez renseigner un nom de classe dans la propriété de l'objet SWbemObjectPath retournée par l'appel de sa méthode Path_.
Vous pouvez ajouter des propriétés à la nouvelle classe par l'appel de la méthode Properties_.
Pour créer une instance d'une classe existante, appelez SWbemServices.SpawnInstance_.
Il ne faut pas confondre les objets des API WMI (SwbemLocator, SwbemObject, SwbemServices) et les classes d'objets ou les instances d'objets du référentiel WMI (Win32_Directory, Win32_Process…).
Les premiers de type TObject ou COM sont manipulables directement sous Delphi.
Exemple :
Code delphi : | Sélectionner tout |
WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '','', wbemConnectFlagUseMaxWait, nil);
L'exemple suivant n'est pas possible :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 | Var NewProcess: Win32_Process; Begin NewProcess:=Win32_Process.Create('Notepad.exe','c:\temp',Nil, ProcessId); End; |
De nombreux objets WMI renvoient des collections de données. Ces collections sont du type interface IEnumVariant (consultez ce lien pour plus de détails sur l'interface IENumVariant).
Le code suivant permet d'afficher toutes les sous-classes de l'espace de nom ROOT\CIMV2.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | procedure TForm1.BTConnexionClick(Sender: TObject); var WmiService: SWbemServices; WmiObject: SWbemObject; wmiObjectSet: SWbemObjectSet; WmiObjectPath: SWbemObjectPath; ObjectEnumerator: IEnumVariant; ArrayVariant: OleVariant; // Tableau de variant NumberItem: LongWord; ClasseList: TStringList; begin try WMILocator:= TSWbemLocator.Create(self); // crée une liste pour le tri // permet de comparer le résultat avec celui des outils WMI de MS ClasseList := TStringList.Create; ClasseList.Sorted:=True; Memo1.Lines.Clear; // Création d'une connexion à un espace de nom local // ici le nom de l'espace de nom cible est : CIMV2 // L'appel renvoie un objet SWbemServices WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); // Retrouve la collection d'objet SWbemObject contenant toutes les sous-classes // immédiates de l'espace de nom courant WmiObjectSet:= WmiService.SubclassesOf('',wbemFlagReturnWhenComplete,Nil); //+wbemQueryFlagShallow limite aux sous-Classes immédiates // Affecte un énumérateur pour la collection d'objet SWbemObject ObjectEnumerator:= (WmiObjectSet._NewEnum) as IEnumVariant; // Retourne NumberItem éléments dans le tableau ArrayVariant, // ici 1 élément est demandé while (ObjectEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin // Récupère l'objet SWbemObject courant de la collection WmiObject := IUnknown(ArrayVariant) as SWBemObject; // Retrouve l'objet SWbemObjectPath contenant toutes les propriétés WmiObjectPath:= WmiObject.Path_; // retrouve le nom de la classe via le chemin d'accès relatif. ClasseList.Add(WmiObjectPath.RelPath); end; Memo1.Lines.Assign(ClasseList); Memo1.Lines.Add(#13#10+IntToStr(ClasseList.Count)+' Classes.'); Finally ClasseList.Free; end; end; |
Code delphi : | Sélectionner tout |
Memo1.Lines.Add(AdjustLineBreaks(wmiObject.GetObjectText_(0)));
Les objets se terminant par Set (SWbemXXXXXSet) proposent des collections d'objets, leur type étant indiqué dans le nom de l'objet.
Par exemple l'objet SwbemPropertySet contient un collection d'objets de type SwbemProperty.
Objets de type collection (enumerators) :
SwbemPropertySet, SWbemNamedValueSet, SWbemPrivilegeSet, SWbemQualifierSet, SWbemMethodSet
Les propriétés sont des noms qui décrivent une ressource gérée. Les classes utilisent des propriétés pour décrire des choses comme l'identité, la configuration, et l'état d'une ressource gérée. Par exemple les services (Win32_Service) ont un nom, un nom d'affichage, une description, un type de démarrage, et un statut.
Chaque propriété a un nom, un type, et des qualificateurs de propriété facultatifs. Certaines propriétés peuvent être des clés permettant l'unicité sur des noms d'instance par exemple.
L'objet SWbemProperty représente une propriété d'un objet géré, on ne peut créer ce type d'objet.
- CIMType
Type de la propriété. - IsArray
Indique si la propriété est un tableau. - IsLocal
Indique si c'est une propriété locale.
Une valeur False indique que la propriété est héritée d'une autre classe. - Name
Nom de la propriété. - Origin
Contient la classe d'origine de cette propriété. Recherche le nom de la classe de WMI dans laquelle cette propriété a été déclarée. Pour les classes avec des hiérarchies d'héritage profond, il est souvent souhaitable de connaître quelles propriétés ont été déclarées et dans quelle classe.
Si la propriété est locale (voir SWbemQualifier.IsLocal), cette valeur est identique à la classe propriétaire. - Qualifiers_
Objet de type SwbemQualiferSet, qui est une collection des qualificateurs de la propriété. - Value
Valeur actuelle de la propriété. C'est la propriété d'automation par défaut de cet objet (c'est un objet de type variant)
Le code suivant énumère une collection et affiche pour chaque élément le nom de la propriété et son contenu :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | procedure WMIEnumereProperty( WmiService:SWbemServices; WmiPropertySet: SWbemPropertySet; Liste: TStrings); //Enumère une collection et affiche pour chaque élément le nom de la propriété et son contenu. //Détermine si le qualificateur Key de la propriété existe. var WmiProperty : SWBemProperty; Enumerateur: IEnumVariant; ArrayVariant: OleVariant; // Tableau de variant NombreItem: LongWord; KeyQualificateur: String; begin Enumerateur:= (WmiPropertySet._NewEnum) as IEnumVariant; while (Enumerateur.Next(1, ArrayVariant, NombreItem) = S_OK) do begin WmiProperty := IUnknown(ArrayVariant) as SWBemProperty; KeyQualificateur:=WMIGet_KeyQualifierOfProperty(WmiService,WmiProperty); If KeyQualificateur<>'' then Liste.add('Clé ['+KeyQualificateur+'] = '+ WmiPropertySet.Item(KeyQualificateur,0).Get_Value); Liste.Add(AdjustLineBreaks('Propriété '+WmiProperty.name+' = '+ WMIPropertyToStr(WmiService,WmiProperty))); end; end; |
La procédure suivante recherche la qualificateur nommé 'Key'. Il indique que la propriété est une clef de classe et est employée pour identifier des instances uniques d'une ressource gérée dans une collection de ressources identiques.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Function WMIGet_KeyQualifierOfProperty( WmiService:SWbemServices; WmiProperty: SWbemProperty):String; //Recherche pour une propriété le qualificateur KEY. //Cette clé déterminant l'unicité dans une classe d'association par exemple. begin try WmiProperty.Qualifiers_.Item('Key',0); Result:=WmiProperty.name; // cette propriéte est une clé ( Key Qualifier) // Une clé par propriété, mais plusieurs // propriétés peuvent former une clé composée. except on E:EOleException do Result:=''; end; end; |
Note :
La fonction WMIGet_KeyQualifierOfProperty recherche pour une propriété le qualificateur KEY. Cette clé détermine par exemple l'unicité dans une classe d'association. Ce qualificateur peut ne pas exister, ce qui est souvent le cas. L'exception wbemErrNotFound (0x80041002) ou "Objet non-trouvé" est donc très souvent déclenchée dans l'EDI sans que cela soit à proprement parler une erreur.
Les qualificateurs sont des adjectifs qui fournissent des informations additionnelles au sujet de la classe, de la propriété ou de la méthode à laquelle ils s'appliquent. Par exemple le qualificateur de la classe nommé Dynamic répond à la question "Quel est le type de classe de Win32_Service ?".
Dans les premiers temps d'utilisation de WMI, vous rechercherez simplement des informations. Ensuite, si vous souhaitez modifier des propriétés ou appeler des méthodes, les qualificateurs deviennent de plus en plus importants car ils définissent les caractéristiques opérationnelles de la propriété que vous mettez à jour ou de la méthode que vous appelez.
Le code suivant énumère la liste des qualificateurs d'une instance :
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | procedure WMIEnumereQualificateur( WmiQualifierSet: SWbemQualifierSet; Liste: TStrings); //Enumère une collection et affiche, pour chaque élément, le nom du qualificateur et son contenu. var WmiQualifier: SWBemQualifier; Enumerateur: IEnumVariant; ArrayVariant: OleVariant; // Tableau de variant NombreItem: LongWord; begin Enumerateur:= (WmiQualifierSet._NewEnum) as IEnumVariant; while (Enumerateur.Next(1, ArrayVariant, NombreItem) = S_OK) do begin WmiQualifier := IUnknown(ArrayVariant) as SWbemQualifier; // Retrouve le nom et la valeur du qualificateur. Liste.Add('Nom du Qualificateur : '+WmiQualifier.Name+'='+WMIVariantToStr(WmiQualifier.Get_Value) ); end; end; |
Exemple d'appel :
Code delphi : | Sélectionner tout |
WMIEnumereQualificateur( WmiObject.Qualifiers_,Memo1.Lines);
Un chemin d'objet d'instance décrit l'emplacement d'une instance d'une classe donnée dans un espace de nom spécifique.
À partir d'une instance de type SWBemObject on utilise sa propriété Path_ de type SWbemObjectPath qui représente son chemin d'accés dans le référentiel.
Sa propriété path_ affiche son chemin complet et sa propriété RelPath affiche son chemin relatif.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | procedure WMIEnumereObjetRelPath( WmiObjectSet: SWbemObjectSet; Liste: TStrings); //Enumère une collection et affiche, pour chaque élément, le chemin relatif. var WmiObject: SWbemObject; Enumerateur: IEnumVariant; ArrayVariant: OleVariant; NombreItem: LongWord; begin Enumerateur:= (WmiObjectSet._NewEnum) as IEnumVariant; while (Enumerateur.Next(1, ArrayVariant, NombreItem) = S_OK) do begin WmiObject := IUnknown(ArrayVariant) as SWBemObject; //Affiche au format MOF Liste.Add(WmiObject.Path_.RelPath); end; end; |
Le membre SWbemProperty.CIMType d'une propriété détermine son type de donnée.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | Function WMIPropertyToStr(WmiService:SWbemServices; WmiProperty : SWbemProperty):String; //Convertit une propriété en chaîne de caractères. var sValue: String; Count: Integer; Value: Variant; WmiObjet : SWbemObject; begin try Value:=WmiProperty.Get_Value; sValue := ''; if VarIsNull(Value) then sValue := 'Is Null' else try case WmiProperty.CIMType of //Voir l'énumération WbemCimTypeEnum wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeSint16, wbemCimtypeUint16, wbemCimtypeSint32, wbemCimtypeUint32, wbemCimtypeSint64, wbemCimtypeUint64: if VarIsArray(Value) then begin if VarArrayHighBound(Value, 1) > 0 then for Count := 1 to VarArrayHighBound(Value, 1) do sValue := sValue + ' ' + IntToStr(Value[Count]); end else sValue := IntToStr(Value); wbemCimtypeReal32, wbemCimtypeReal64: sValue := FloatToStr(Value); wbemCimtypeBoolean: if Value then sValue := 'True' else sValue := 'False'; // Caractère unicode 16 bit au format de caractère universel Set–2 (UCS-2) wbemCimtypeChar16, // Chaîne de caractères unicode wbemCimtypeString: if VarIsArray(Value) then begin if VarArrayHighBound(Value, 1) > 0 then try for Count := 1 to VarArrayHighBound(Value, 1) do sValue := sValue + ' ' + Value[Count]; except on E: EConvertError do ShowMessage(E.Message); end; end else sValue := Value; wbemCimtypeDatetime: sValue := Value; (* Voir note en fin de méthode *) wbemCimtypeReference: begin // Récupére l'objet référencé WmiObjet:=WmiService.Get(Value,wbemFlagReturnWhenComplete,Nil); sValue:=AdjustLineBreaks(WmiObjet.GetObjectText_(0)) end; (* Voir note en fin de méthode *) //Renvoie le path de la propriété de type Objet wbemCimtypeObject : begin // Récupére l'objet imbriqué // **Peut-il être un tableau d'objets ? WmiObjet:=IUnknown(WmiProperty.Get_Value) as SWbemObject ; sValue:=WmiObjet.Path_.Relpath; end; end; // case except on E: EVariantError do ShowMessage('WMIPropertyToStr : Erreur de conversion de variant'); end; Finally Result:=sValue; end; end; |
wbemCimtypeReference :
Le mot-clé référence MOF décrit un chemin d'objet et mappe un type automation VT_BSTR.
Le chemin d'objet peut être un chemin complet vers un serveur et un espace de nom, ou un chemin relatif vers un autre objet dans le même espace de nom.
wbemCimtypeObject :
Encapsulation d'objet dans une classe.
Un objet encapsulé est un objet d'une classe qui existe dans une déclaration de classe ou d'instance d'une autre classe.
Par exemple, la classe de Win32_SecurityDescriptor contient les objets inclus Win32_Trustee.
Chacun des objets de Win32_Trustee contient un objet Win32_ACE.
WMI ne limite pas la profondeur à laquelle une classe peut avoir des objets encapsulés.
Cependant, employer une autre conception, telle que créer une classe d'association peut rendre un schéma plus maniable.
La gestion des exceptions devra être adaptée à votre contexte d'utilisation. L'appel à Showmessage étant ici à titre indicatif.
Une instance représente un objet ou un élément du monde réel. Une instance est toujours créée à partir d'une classe représentant le template de l'objet réel. Par exemple, une instance de disque représente un disque réel et son template est défini par la classe Disk.
Le référentiel peut vous renvoyer toutes les instances d'une classe particulière. On utilise à cette fin la méthode InstancesOf de l'objet SWbemServices.
On lui passe en paramètre le nom de la la classe WMI( Win32_OperatingSystem), la profondeur ( wbemQueryFlagShallow), c'est à dire si on parcourt toute la hiérarchie de la classe ou non, et si on attend ou non la fin de l'appel( wbemFlagReturnWhenComplete).
Le dernier paramètre peut être utilisé pour récupérer des instances partielles, c'est à dire que WMI renverra seulement les propriétés indiquées dans l'objet SWbemNamedValueSet. Ceci pouvant réduire l'occupation mémoire et le trafic réseau lors d'appel distant.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | procedure TForm1.BTConnexionClick(Sender: TObject); var WMILocator: TSWbemLocator; WmiService: SWbemServices; WmiObject: SWbemObject; wmiObjectSet: SWbemObjectSet; ObjectEnumerator: IEnumVariant; ArrayVariant: OleVariant; NumberItem: LongWord; begin WMILocator:= TSWbemLocator.Create(self); try WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); // Retrouve la collection d'instance de la classe Win32_OperatingSystem // de l'espace de nom courant wmiObjectSet := wmiService.InstancesOf('Win32_OperatingSystem', wbemFlagReturnWhenComplete+wbemQueryFlagShallow, nil); ObjectEnumerator:= (WmiObjectSet._NewEnum) as IEnumVariant; while (ObjectEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin WmiObject := IUnknown(ArrayVariant) as SWBemObject; // Retrouve la propriété de l'instance au format MOF Memo1.Lines.Add(AdjustLineBreaks(wmiObject.GetObjectText_(0))); end; Finally WMILocator.Free; end; end; |
On utilise l'objet ISWbemNamedValue, il représente une valeur simple nommée qui appartient à une collection SWbemNamedValueSet.
L'objet ISWbemNamedValue n'a pas de méthode.
Les méthodes et propriétes de l'objet SWbemNamedValueSet sont principalement utilisées pour envoyer des informations supplémentaires aux providers lors de certains appels vers WMI.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | procedure TForm1.btInstancePartielClick(Sender: TObject); // Retrouve une instance partielle var WMILocator: TSWbemLocator; WmiService: SWbemServices; WmiObject: SWbemObject; WmiProperty: SWbemProperty; WmiPropertySet: SWbemPropertySet; WmiNamedValueSet: TSWbemNamedValueSet; PropertyEnumerator: IEnumVariant; ArrayVariant: OleVariant; NumberItem: LongWord; Value: Olevariant; begin try WMILocator:= TSWbemLocator.Create(self); // Création d'une connexion à un espace de nom local // ici le nom de l'espace de nom cible est : CIMV2 // L'appel renvoie un objet SWbemServices WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); WmiNamedValueSet:= TSWbemNamedValueSet.Create(self); Value:=True; //Contenu de la valeur nommée //'__GET_EXTENSIONS' signale une instance partielle WmiNamedValueSet.Add('__GET_EXTENSIONS',Value,0); // iFlags toujours à zéro. WmiNamedValueSet.Add('__GET_EXT_CLIENT_REQUEST',Value,0); // WmiNamedValueSet.Add(' __GET_EXT_KEYS_ONLY',Value,0); //Renvoie seulement les clés //Tableaux des propriétés à renvoyer Value:=VarArrayCreate([1,2], varOleStr); Value[1]:='Name'; Value[2]:='State'; //'__GET_EXT_PROPERTIES' indique la liste des propriétés à renvoyer WmiNamedValueSet.Add('__GET_EXT_PROPERTIES',Value,0); // Retrouve l'instance du service Telnet de la classe Win32_Service // de l'espace de nom courant WmiObject := wmiService.Get('Win32_Service.Name="TlntSvr"', 0, WmiNamedValueSet.DefaultInterface); // Retrouve la collection d'objets WmiProperty contenant toutes les propriétés WmiPropertySet:= WmiObject.Properties_; Memo1.Lines.Add(IntToStr(WmiPropertySet.Count)); // Affecte un énumérateur pour la collection d'objets WmiProperty PropertyEnumerator:= (WmiPropertySet._NewEnum) as IEnumVariant; while (PropertyEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin // Récupére l'objet SWBemProperty courant de la collection WmiProperty := IUnknown(ArrayVariant) as SWBemProperty; // Retrouve le nom et la valeur de la propriété. if not VarIsNull(WmiProperty.Get_Value) then Memo1.Lines.Add(WmiProperty.name+'='+WMIPropertyToStr(WmiService,WmiProperty)); end; Finally WmiNamedValueSet.Free; WMILocator.Free; end; end; |
L'exemple suivant ne fait qu'imbriquer des appels d'énumérateurs et affiche la propriété 'Name' des instances de la classe Win32_Service, i.e. le nom du service.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | procedure TForm1.BTConnexionClick(Sender: TObject); var WMILocator: TSWbemLocator; WmiService: SWbemServices; WmiObject: SWbemObject; wmiObjectSet: SWbemObjectSet; WmiProperty: SWbemProperty; WmiPropertySet: SWbemPropertySet; PropertyEnumerator, ObjectEnumerator: IEnumVariant; ArrayVariant: OleVariant; // Tableau de variant NumberItem: LongWord; begin WMILocator:= TSWbemLocator.Create(self); try WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); // Retrouve la collection d'instances de la classe Win32_Service // de l'espace de nom courant wmiObjectSet := wmiService.InstancesOf('Win32_Service', wbemFlagReturnWhenComplete+wbemQueryFlagShallow, nil); ObjectEnumerator:= (WmiObjectSet._NewEnum) as IEnumVariant; while (ObjectEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin WmiObject := IUnknown(ArrayVariant) as SWBemObject; // Retrouve la collection d'objets WmiProperty contenant toutes les propriétés WmiPropertySet:= WmiObject.Properties_; // Affecte un énumérateur pour la collection d'objet WmiProperty PropertyEnumerator:= (WmiPropertySet._NewEnum) as IEnumVariant; // Aprés l'affectation précédente, on peut réutiliser la variable ArrayVariant while (PropertyEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin // Récupére l'objet SWBemProperty courant de la collection WmiProperty := IUnknown(ArrayVariant) as SWBemProperty; // Retrouve le nom du service via la propriété de classe nommée 'Name'. // Implicite : propriété de type Chaine de caractéres. // WmiProperty.CIMType = wbemCimtypeString If WmiProperty.name='Name' then Memo1.Lines.Add(WmiProperty.Get_Value); end; end; Finally WMILocator.Free; end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | // Affecte un énumérateur pour la collection d'objet SWbemObjectSet ObjectEnumerator:=TEnumVariant.Create(wmiService.InstancesOf('systemrestore', wbemFlagReturnWhenComplete+wbemQueryFlagShallow, nil)); For MonObjetWMI in ObjectEnumerator do begin // Affecte un énumérateur pour la collection d'objets SWbemPropertySet PropertyEnumerator:= TEnumVariant.Create((MonObjetWMI as SWBemObject).Properties_); For MaProprieteWMI in PropertyEnumerator do begin // Retrouve le nom du service via la propriété de classe nommée 'Name'. With (MaProprieteWMI as SWBemProperty) do begin If Name='Name' ... |
Vous pouvez employer les propriétés de l'objet SWbemMethod pour inspecter la définition d'une méthode d'un objet WMI.
Cet objet ne peut pas être créé.
Pour appeler une méthode, vous devez employer soit l'accès direct (SWbemObject.ExecMethod_) sur un objet de type SWbemObject (mode recommandé) soit l'appel indirect via la méthode SWbemServices.ExecMethod.
L'exemple suivant crée un process, notepad.exe, en exécutant la méthode Create de la classe Win32_Process.
Note :
Les variables BTDeleteProcess et BTCreateProcess référencent des composants TButton qui autorisent ou non la création d'un process unique via l'IHM.
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | var ProcessID: OleVariant; //Variable Globale ... procedure TForm1.BTCreateProcessClick(Sender: TObject); var WMILocator : TSWbemLocator; Process, NewProcess, Instance_inParameters : SWbemObject; WmiProperty : SWbemProperty; ProcessMethod : ISWbemMethod; PropertyCommandLine, PropertyReturnValue : OleVariant; begin WMILocator:= TSWbemLocator.Create(self); try WmiService:= WMILocator.ConnectServer('.', 'ROOT\CIMV2', '', '', '', '', wbemConnectFlagUseMaxWait, nil); // Retrouve la définition de la classe Win32_Process Process:=WmiService.Get('Win32_Process',0,Nil); // Récupère, à partir de la collection de méthode, // la définition de la méthode 'Create' de la classe Win32_Process ProcessMethod:=Process.Methods_.Item('Create', 0); // La définition de la méthode 'Create' correspond à : { Win32_Process.Create(IN CommandLine string , IN CurrentDirectory string , IN ProcessStartupInformation Win32_ProcessStartup , OUT ProcessId uint32) Valeur de retour : [Out] ProcessId uint32 ; [out] ReturnValue uint32 ; } // Crée une nouvelle instance de la méthode '.Create' de la classe Win32_Process // alloue l'espace mémoire pour manipuler ces paramètres. // ProcessMethod.InParameters.Properties_ contient la liste des paramètres de la méthode Instance_inParameters:= ProcessMethod.InParameters.SpawnInstance_(0); // L'appel suivant est possible : // NewInParametersInstance:= Process.Methods_.Item('Create',0).inParameters.SpawnInstance_(0); // Retrouve la propriété 'CommandLine' de la méthode '.Create' WmiProperty:= Instance_inParameters.Properties_.Item('CommandLine',0); // Nom du programme à exécuter PropertyCommandLine:= 'Notepad.exe'; //Renseigne la valeur de la propriété 'CommandLine' de la méthode '.Create' WmiProperty.Set_Value(PropertyCommandLine); //Crée un process via la Méthode '.Create' NewProcess:= Process.ExecMethod_('Create', Instance_inParameters, wbemFlagReturnWhenComplete, nil); { Un objet OutParameters est créé par la méthode exécutée } // Recupère la valeur de retour de la méthode via la propriété 'ReturnValue' PropertyReturnValue:= NewProcess.Properties_.Item('ReturnValue', 0); {Code de retour : 0 Successful completion 2 Access denied 3 Insufficient privilege 8 Unknown failure 9 Path not found 21 Invalid parameter } if PropertyReturnValue.Value = 0 then begin // Réutilise la propriété pour récupérer l'ID de process PropertyReturnValue:= NewProcess.Properties_.Item('ProcessId', 0); ProcessID:=PropertyReturnValue.Value; MessageBox(0, PChar('Process crée.'+#10#13+'Pid : '+inttostr(ProcessID)), PChar(Form1.Caption), MB_OK); BTDeleteProcess.Enabled:= True; BTCreateProcess.Enabled:= False; SetForegroundWindow(Form1.Handle); end else // Une erreur lors de la création du process MessageBox(0, PChar('Erreur '+inttostr(PropertyReturnValue.Value)+' lors de la création du process.'), PChar(Form1.Caption), MB_OK); Finally WMILocator.Free; end; end; |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | var Instance_inParameters : SWbemObject; WmiProperty : SWbemProperty; ProcessMethod : ISWbemMethod; PropertyReturnValue : OleVariant; ObjectWmi, ParametreOut : SWBemObject; PropertyReason : OleVariant; begin // Retrouve une instance de la classe Win32_Process // la propriété Handle est la clé de la classe ObjectWmi:= WmiService.Get('Win32_Process.Handle="' + inttostr(ProcessId)+ '"', 0, nil); // Retrouve la méthode Terminate ProcessMethod:= ObjectWmi.Methods_.Item('Terminate', 0); Instance_inParameters:= ProcessMethod.InParameters.SpawnInstance_(0); // La méthode Terminate a 1 paramètre nommé Reason // Reason : [in] Exit code for the process and for all threads terminated as a result of this call. WmiProperty:= Instance_inParameters.Properties_.Item('Reason',0); PropertyReason:= 0; WmiProperty.Set_Value(PropertyReason); // Execute la méthode ParametreOUT:= ObjectWmi.ExecMethod_('Terminate', Instance_inParameters, wbemFlagReturnWhenComplete, nil); // Récupére le code de sortie PropertyReturnValue:= ParametreOUT.Properties_.Item('ReturnValue', 0); if PropertyReturnValue.Value = 0 then begin BTCreateProcess.Enabled:= True; BTDeleteProcess.Enabled:= False; end else MessageBox(0, PChar('Supression du process impossible.'), PChar(Form1.Caption), MB_OK); end; |
Cet exemple a été testé avec un compte autorisé, en l'occurrence avec le compte administrateur.
L'accès à certaines classes ou données WMI exige un privilège qui n'est pas activé par défaut. Par exemple pour utiliser la classe Win32_NTEventlogFile vous devez inclure le privilège wbemPrivilegeSecurity.
Note :
Ce privilège n'ajoute pas de droit au compte utilisé lors de l'opération.
On utilise sur un objet SWbemServices sa propriété Security_ qui est du type SWbemSecurity.
On ajoute le privilège via la méthode Add de la propriété Privileges qui est une collection de privilèges.
Code delphi : | Sélectionner tout |
1 2 | //Ajoute au process appelant le privilège wbemPrivilegeShutdown (SE_SHUTDOWN_NAME) wmiService.Security_.Privileges.Add(wbemPrivilegeShutdown, True); |
Code delphi : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | procedure TForm1.BtConnexionClick(Sender: TObject); var WmiService: SWbemServices; WmiObjet: SWbemObject; wmiObjetSet: SWbemObjectSet; WmiProperty: SWbemProperty; ObjectEnumerator: IEnumVariant; ArrayVariant: OleVariant; // Tableau de Variant NumberItem: LongWord; ShutdownMethod_inParameters, Shutdown : SWbemObject; PropertyReboot : OleVariant; ShutdownMethod: SWbemMethod; WMILocator: TSWbemLocator; begin WMILocator:= TSWbemLocator.Create(self); // Initialisation try //Permet aux objets d'utiliser l'identité de l'appelant. //C'est le niveau d'usurpation d'identité recommandé //pour l'appel d'API de scripting WMI. WMILocator.Security_.Set_ImpersonationLevel(wbemImpersonationLevelImpersonate ); //WMI utilise la configuration d'authentification par défaut de Windows. WMILocator.Security_.Set_AuthenticationLevel(wbemAuthenticationLevelDefault); // Attention aux majuscules-minuscules pour le password. WmiService:= WMILocator.ConnectServer('NomDeMachine', 'ROOT\CIMV2', 'MonDomaine\MonCompte', 'PasswordDuCompte', '', '', wbemConnectFlagUseMaxWait, nil); except on E:EOleException do begin // S'il s'agit d'un problème de mot de passe E_ACCESSDENIED=$80070005 ShowMessage(StrOriginError(E.ErrorCode)+' ['+IntToHex(E.ErrorCode,8)+'] '+E.Message); Raise; end; end; //Ajoute au process appelant le privilège wbemPrivilegeShutdown (SE_SHUTDOWN_NAME) wmiService.Security_.Privileges.Add(wbemPrivilegeShutdown, True); wmiObjetSet := wmiService.ExecQuery( 'SELECT * FROM Win32_OperatingSystem WHERE Primary=True', 'WQL', wbemFlagReturnImmediately, nil); ObjectEnumerator:= (WmiObjetSet._NewEnum) as IEnumVariant; while (ObjectEnumerator.Next(1, ArrayVariant, NumberItem) = S_OK) do begin WmiObjet := IUnknown(ArrayVariant) as SWBemObject; ShutdownMethod:= wmiObjet.Methods_.Item('Win32Shutdown', 0); ShutdownMethod_inParameters:= ShutdownMethod.InParameters; Shutdown:= ShutdownMethod_inParameters.SpawnInstance_(0); WmiProperty := Shutdown.Properties_.Add('Flags', wbemCimtypeSint32, False, 0); PropertyReboot:= EWX_SHUTDOWN; // ou EWX_REBOOT; wmiProperty.Set_Value(PropertyReboot); wmiObjet.ExecMethod_('Win32Shutdown', Shutdown, 0, nil); end; end; |
Notes :
Par défaut, tous les membres du groupe d'utilisateur local sur les systèmes Windows NT/Windows 2000 ont le droit d'accès en lecture seule sur tous les espaces de noms.
Pour modifier les permissions d'accès par défaut sout NT, il faut utiliser l'application Wbemcntl.exe et MMC sous Windows 2000.
Lien MSDN : constante WbemImpersonationLevelEnum
Lien MSDN : constante WbemAuthenticationLevelEnum
Lien MSDN : constante WbemPrivilegeEnum
Proposer une nouvelle réponse sur la FAQ
Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour çaLes sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.