5 Techniques avancées de Script
Transcription
5 Techniques avancées de Script
5. Techniques avancées de Script 97 5 Techniques avancées de Script DescoDev 5. Techniques avancées de Script 98 5- Techniques avancées de Script Nous avons vu au sein des précédents chapitres comment rédiger des scripts à l’aide du langage VBScript et comment s’en servir pour piloter les objets WSH et Scripting. Cependant, on pourrait sans trop de tort se poser la question suivante : « est-ce tout ce dont Windows Script Host est capable ? » Bien sûr que non. Il est sûr que nous avons vu l’ensemble du langage et des outils intrinsèques à Windows Script Host. Cependant, il suffit de les utiliser afin d’accéder aux différentes ressources du système pour voir WSH être capable de redémarrer le système, jouer des sons, créer un compte dans Active Directory, accéder à une base de données, etc. Deux méthodes intrinsèques aux objets Windows Script Host permettent d’ouvrir ces portes. • La méthode CreateObject possède l’avantage de pouvoir créer tout objet exposé par la base de registre du système tel que nous l’avons constaté au chapitre 4. Ainsi, serait-il possible de créer des instances d’Internet Explorer pour afficher des formulaires complexes que l’utilisateur remplirait et que notre script récupérerait ensuite afin de stocker ces informations au sein d’une base de données distante ? Serait-il possible de se connecter au pare-feu de Windows XP afin d’en modifier les configurations? Certainement. La seule difficulté réside dans le fait qu’il nous doit de connaître les modèles d’objets concernés pour réaliser ce tour de force. • La méthode Run, quant à elle, possède l’avantage de pouvoir exécuter tout logiciel présent sur le système y compris RunDLL32.exe, petit exécutable permettant d’accéder à l’ensemble de l’API de Windows, c’est-à-dire toutes les fonctions utilisées par les programmes compilés pour s’exécuter. La difficulté demeurera ici dans le fait qu’il se doit de connaître ces fonctions, les paramètres qu’elles attendent et, non pas le moindre, les effets (quelques fois dévastateurs) qu’elles peuvent avoir sur le système. Quoiqu’il est hors de la prétention de cet ouvrage d’être une documentation complète des différents modèles d’objets et de l’ensemble des fonctions API, voyons tout de même certains trucs qui vous permettront de pousser plus loin l’efficacité et la convivialité de vos scripts. DescoDev 5. Techniques avancées de Script 99 Piloter le pare-feu de Windows XP SP2 L’arrivée non sans tumultes du Service Pack 2 de Windows XP a amenée un pare-feu plus performant et plus flexible. Le but du pare-feu de Windows XP SP2 est de bloquer les tentatives non-sollicitées de communiquer avec le poste. Le pare-feu n’intervient pas sur les communications originant du poste et ce, peu importe le port ou l’application responsable de la communication. Les objets permettant de piloter les configurations réseaux d’un poste XP SP2 sont contenus au sein de l’objet HNetCfg. Cet objet permet d’accéder au pare-feu mais également au partage de connexions Internet ICS, configurations avancées de Internet Explorer 6, etc. Les objets permettant de piloter le pare-feu de Windows XP SP2 sont contenus au sein de l’objet HNetCfg.FwMgr installé lors de l’installation du Service Pack 2. Ainsi, vos scripts pilotant le pare-feu commenceront sensiblement comme suit : Dim objFw Set objFw = WScript.CreateObject("HNetCfg.FwMgr") À partir de ce moment, la variable objFw référence le gestionnaire du pare-feu du poste local et pourra être utilisée afin de le piloter. Une erreur sera soulevée si votre script est exécuté sur un poste ne possédant pas Windows XP SP2. Il peut donc être sage de prévoir un gestionnaire d’erreurs approprié : Dim objFw On Error Resume Next Set objFw = WScript.CreateObject("HNetCfg.FwMgr") If Err.Number Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If L’objet FwMgr expose les quelques membres suivants : Propriété CurrentProfileType LocalPolicy Description Retourne un profil de configuration selon le type spécifié. Documentation incomplète à ce jour. Retourne un objet représentant les stratégies en cours sur le pare-feu. Utilisez cet objet comme point central pour accéder aux propriétés avancées du pare-feu. Méthode Description RestoreDefaults Restaure la configuration originale du pare-feu. IsPortAllowed Retourne si le port TCP ou UDP précisé en paramètre est autorisé. IsICMPTypeAllowed Retourne si le type ICMP précisé en paramètre est autorisé. DescoDev 5. Techniques avancées de Script 100 L’exemple simple suivant permet de restaurer les configurations originales du pare-feu : Dim objFw On Error Resume Next Set objFw = WScript.CreateObject("HNetCfg.FwMgr") If Err.Number Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If objFw.RestoreDefaults CH05\FW\FW RestaurerDefaut.vbs La propriété LocalPolicy de l’objet FwMgr expose l’ensemble des stratégies appliquées au pare-feu sous forme d’un autre objet du type FwPolicy. Ce dernier objet expose une seule propriété, CurrentProfile, qui retourne un objet de type FwProfile. Quoique cela semble compliqué au premier abord, retenez simplement le script suivant qui permet d’accéder aux propriétés du pare-feu de Windows XP SP2. Dim objFw, objPrfl On Error Resume Next Set objFw = WScript.CreateObject("HNetCfg.FwMgr") If Err.Number Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If Set objPrfl = objFw.LocalPolicy.CurrentProfile À partir de ce point, la variable objPrfl permettra d’accéder aux configurations du pare-feu. La nature de l’objet FwProfile est encore obscure puisque la documentation officielle est encore incomplète à ce sujet mais il semblerait que Microsoft prévoit de mettre en place plusieurs profils qui contiendraient des configurations différentes. Ces profils seraient du type profil local, profil de domaine, profil par défaut, etc. DescoDev 5. Techniques avancées de Script 101 L’objet FwProfile retourné par la propriété CurrentProfile expose les propriétés suivantes: Propriété Description Retourne une collection d’objets FwAuthorizedApplication représentant chacun une application autorisée par le pare-feu. Retourne une collection d’objets FwAuthorizedApplication représentant ExceptionsNotAllowed une application autorisée par le pare-feu. FirewallEnabled Détermine/Retourne si le pare-feu est activé. AuthorizedApplications Retourne une collection d’objets FwOpenPort représentant chacun un port TCP ou UDP autorisé ainsi que les adresses IP concernées. Retourne un objet FwIcmpSettings représentant les configurations IcmpSettings du pare-feu concernant le protocole ICMP. Détermine/Retourne si les notifications lancées lorsqu’une exception NotificationsDisabled est rencontrée sont activées. Retourne un objet FwRemoteAdminSettings représentant les RemoteAdminSettings configurations de l’administration distante. Retourne une collection d’objets FwService représentant chacun un Services service (port + étendue) autorisé par le pare-feu. Retourne le type de profil concerné par l’instance FwProfile en cours Type (domaine, locale, défaut). GloballyOpenPorts Activer et désactiver le pare-feu de Windows XP SP2 Le pare-feu ICF de Windows XP SP2 peut être activé ou désactivé à partir des propriétés des connexions réseau. Votre script peut activer et désactiver le pare-feu en altérant la valeur de la propriété FirewallEnabled de l’objet FwProfile retourné par la propriété CurrentProfile. Le script suivant active et désactive le pare-feu selon son état actuel. Ainsi, le pare-feu est désactivé s’il était activé et vice-versa. Dim objFw, objPrfl On Error Resume Next Set objFw = WScript.CreateObject("HNetCfg.FwMgr") If Err.Number Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If Set objPrfl = objFw.LocalPolicy.CurrentProfile objPrfl.FirewallEnabled = Not objPrfl.FirewallEnabled MsgBox "Pare-feu activé : " & objPrfl.FirewallEnabled CH05\FW\FW Activation.vbs DescoDev 5. Techniques avancées de Script 102 Autoriser et enlever des applications Lorsque le pare-feu ICF de Windows XP SP2 est activé, l’ensemble des communications IP sont gérées par le parefeu. Cependant, Windows XP SP2 permet à des programmes spécifiques de communiquer par le biais du pare-feu peu importe le protocole et le port sollicité. Votre script peut autoriser une application de communiquer via le pare-feu en accédant à la collection AuthorizedApplications de l’objet FwProfile retourné par la propriété CurrentProfile. En ce faisant, votre script pourra récupérer la liste des applications autorisées ou encore utiliser la méthode Add afin d’y ajouter un objet AuthorizedApplication préalablement instancié et configuré. '******** Instanciation d’une application autorisée ************' Set objApp = CreateObject("HNetCfg.FwAuthorizedApplication") L’objet FwAuthorizedApplication expose les propriétés suivantes : Propriété Description Enabled Valeur booléenne activant ou désactivant l’application. Détermine/Retourne la version de protocole IP prise en charge (non pris en charge pour l’instant. Ne pas utiliser). Nom de l’application tel qu’il sera affiché au sein de la liste des applications de la boîte de dialogue de configuration du pare-feu. Chemin complet de l’exécutable autorisé. Le chemin doit être complet mais peut contenir des variables d’environnement. Détermine/Retourne la liste des adresses IP distantes autorisées à utiliser cette application. Il est possible de spécifier toute adresse IP en spécifiant simplement un astérisque (*). Si l’astérisque est spécifié, seule cette valeur doit être spécifiée. Sinon, des adresses séparées les unes des autres par un point-virgule (;) peuvent être spécifiées. Spécifiez le masque de sous-réseau après chaque adresse en le précédant d’une barre oblique (/). IpVersion Name ProcessImage FileName RemoteAddresses Exemple : 10.10.0.2/255.0.0.0;10.10.0.2/8 Détermine/Retourne une étendue d’adresses IP distantes autorisées à utiliser cette application. Les valeurs numériques possibles sont : Scope 0 = Toutes (défaut) 1 = Sous-réseau local DescoDev 5. Techniques avancées de Script 103 Le script suivant ajoute l’utilitaire NsLookup à la liste d’exceptions du pare-feu de Windows XP. Option Explicit Const NET_FW_SCOPE_ALL = 0 Const NET_FW_SCOPE_LOCAL_SUBNET = 1 '********* Création du gestionnaire du pare-feu **************' On Error Resume Next Set objFwMgr = CreateObject("HNetCfg.FwMgr") If Err <> 0 Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If Set objPrfl = objFw.LocalPolicy.CurrentProfile '******* Création d’un objet AuthorizedApplication ***********' Set objApp = CreateObject("HNetCfg.FwAuthorizedApplication") objApp.Name = "NsLookup" objApp.ProcessImageFileName = "%windir%\system32\nslookup.exe" objApp.Scope = NET_FW_SCOPE_ALL 'Ou NET_FW_SCOPE_LOCAL_SUBNET objApp.Enabled = True '** Ajoute l’application dans les apps autorisées du profil **' objProfile.AuthorizedApplications.Add objApp CH05\FW\FW AutoriserNSLookup.vbs Un script nommé FW AutoriserApp.vbs situé au sein du même répertoire permet d’autoriser toute application pour laquelle le chemin complet est précisé en argument de ligne de commande. L’unique différence entre ce script et celui précédemment présenté est que le chemin de l’application ainsi que son nom sont récupérés dynamiquement à partir des paramètres précisés à l’invite de commande. Exemple de l’utilisation de ce script au sein duquel l’utilitaire nslookup.exe est ajouté aux applications autorisées par le pare-feu : FW AutoriserApp.vbs nslookup c:\windows\system32\nslookup.exe DescoDev 5. Techniques avancées de Script 104 Autoriser et enlever des ports Windows XP SP2 permet à des ports TCP et UDP spécifiques de communiquer par le biais du pare-feu peu importe l’application utilisée. Votre script peut autoriser les diverses applications de communiquer via un port spécifique du pare-feu en accédant à la collection AuthorizedPorts de l’objet FwProfile retourné par la propriété CurrentProfile. En ce faisant, votre script pourra récupérer la liste des ports autorisés ou encore utiliser la méthode Add afin d’y ajouter un objet AuthorizedPort préalablement instancié et configuré. '************* Instanciation d’un port autorisé ***************' Set objApp = CreateObject("HNetCfg.FwAuthorizedPort") L’objet FwAuthorizedPort expose les propriétés suivantes : Propriété BuiltIn Enabled IpVersion Name Port Protocol RemoteAddresses Description Retourne une valeur booléenne spécifiant si le port est défini par le système (propriété en lecture seule). Valeur booléenne activant ou désactivant le port. Détermine/Retourne la version de protocole IP prise en charge (non pris en charge pour l’instant. Ne pas utiliser). Nom du port tel qu’il sera affiché au sein de la liste des ports de la boîte de dialogue de configuration du pare-feu. Détermine/Retourne la valeur numérique entière indiquant le port TCP ou UDP spécifié. Détermine/Retourne la valeur numérique entière indiquant le protocole IP concerné où TCP = 6 et UDP = 17. Détermine/Retourne la liste des adresses IP distantes autorisées à utiliser ce port. Il est possible de spécifier toute adresse IP en spécifiant simplement un astérisque (*). Si l’astérisque est spécifié, seule cette valeur doit être spécifiée. Sinon, des adresses séparées les unes des autres par un point-virgule (;) peuvent être spécifiées. Spécifiez le masque de sous-réseau après chaque adresse en le précédant d’une barre oblique (/). Exemple : 10.10.0.2/255.0.0.0;10.10.0.2/8 Détermine/Retourne une étendue d’adresses IP distantes autorisées à utiliser ce port. Les valeurs numériques possibles sont : Scope 0 = Toutes (défaut) 1 = Sous-réseau local DescoDev 5. Techniques avancées de Script 105 Le script suivant ajoute le port 53 UDP (Services de résolution de noms DNS) à la liste d’exceptions du pare-feu de Windows XP : Option Explicit Const NET_FW_SCOPE_ALL = 0 Const NET_FW_SCOPE_LOCAL_SUBNET = 1 '********* Création du gestionnaire du pare-feu **************' On Error Resume Next Set objFwMgr = CreateObject("HNetCfg.FwMgr") If Err <> 0 Then MsgBox "Impossible de connecter le pare-feu." WScript.Quit End If Set objPrfl = objFw.LocalPolicy.CurrentProfile '*********** Création d’un objet AuthorizedPort **************' Set objPort = CreateObject("HNetCfg.FwAuthorizedPort") objPort.Name = "DNS" objPort.Port = 53 objPort.Protocol = 17 '*** UDP objPort.Scope = NET_FW_SCOPE_ALL objPort.Enabled = True 'Ou NET_FW_SCOPE_LOCAL_SUBNET '***** Ajoute le port dans les ports autorisés du profil *****' objProfile.AuthorizedPorts.Add objPort CH05\FW\FW AutoriserDNS.vbs Un script nommé FW AutoriserPort.vbs situé au sein du même répertoire permet d’autoriser tout port et protocole précisés en argument de ligne de commande. L’unique différence entre ce script et celui précédemment présenté est que le numéro de port, le protocole ainsi que son nom sont récupérés dynamiquement à partir des paramètres précisés à l’invite de commande. Exemple de l’utilisation de ce script au sein duquel le port 25 TCP (SMTP) ajouté aux ports autorisés par le pare-feu : FW AutoriserPort.vbs SMTP 25 6 DescoDev 5. Techniques avancées de Script 106 Piloter des formulaires Html L’une des lacunes de Windows Script Host réside dans l’affichage et la saisie d’informations auprès de l’utilisateur. Les seules fonctions prévues demeurent la boîte de message (MsgBox) et la boîte de saisie (InputBox) dont les fonctionnalités sont grandement limitées. Cependant, Windows Script Host peut piloter Internet Explorer qui lui-même possède les fonctionnalités pour piloter des formulaires Html. Ainsi, il serait possible à un script Windows Script Host de demander l’affichage d’un formulaire comme le suivant duquel l’ensemble des informations seraient récupérées avant d’être traitées par le script : Créons d’abord le document Html permettant à l’utilisateur de saisir les informations désirées. Puisqu’il ne s’agit pas ici d’un ouvrage portant sur le Html et les langages dérivés, nous nous contenterons de l’essentiel. Disons simplement que les scripts WSH pourront accéder en lecture et écriture aux balises <INPUT>, <TEXTAREA> et <SELECT> déposées à l’intérieur d’un formulaire Html. Créez un nouveau fichier texte et renommez-le Demande.htm. Ouvrez votre fichier à l’aide de Bloc-Note puis inscrivez-y le balisage de la page suivante avant de le sauvegarder. Ceux qui maîtrisent leur Html pourront parfaire le code à leur goût. DescoDev 5. Techniques avancées de Script 107 <BODY> <FORM Name="frm"> <TABLE> <TR> <TD ALIGN="Right">Utilisateur:</TD> <TD WIDTH="30%"><INPUT Name="txtUtilisateur" Disabled></TD> <TD ALIGN="Right">Poste:</TD> <TD WIDTH="30%"><INPUT Name="txtPoste" Disabled></TD> </TR> <TR> <TD ALIGN="Right">Date:</TD> <TD><INPUT Name="txtDate" Disabled></TD> <TD ALIGN="Right">Heure:</TD> <TD><INPUT Name="txtHeure" Disabled></TD> </TR> <TR> <TD ALIGN="Right" VAlign="Top">Problème:</TD> <TD ColSpan="3"> <TEXTAREA Name="txtProbleme" ROWS="5"></TEXTAREA> </TD> </TR> <TR> <TD ALIGN="Right">Gravité:</TD> <TD ColSpan="3"><SELECT> <OPTION Value="1">Faible</OPTION> <OPTION Value="2" SELECTED>Moyenne</OPTION> <OPTION Value="3">Haute</OPTION> <OPTION Value="4">Très haute</OPTION> </SELECT> </TD> </TR> <TR> <TD ALIGN="Right" ColSpan="2"><P> </P> <A HREF="">Envoyer</A> <P> </P> </TD> <TD ColSpan="2"><P> </P> <A HREF="">Annuler</A> <P> </P> </TD> </TR> </TABLE> </FORM> </BODY> CH06\HTML\Demande Service\Demande.htm DescoDev 5. Techniques avancées de Script 108 Lecture et écriture des valeurs des éléments du formulaire L’affichage du document Html peut être ordonnée par le script en créant une instance du navigateur Internet Explorer puis en lui demandant de naviguer à l’adresse du document désiré. Vous remarquerez l’utilisation de WScript.Sleep afin de forcer le script à ne rien faire en attendant qu’Internet Explorer soit dûment démarré. Ceci est nécessaire puisque le démarrage de logiciels s’effectuent de manière asynchrone, c’est-à-dire que la prochaine ligne de code de votre script pourrait s’exécuter avant même qu’Internet Explorer soit pleinement prêt puisqu’il s’exécute dans un thread séparé de celui de Windows Script Host. Dim objIE, objSH, objNT, Chemin '*** Procède à la création de l’objet Internet Explorer ******' Set objIE = WScript.CreateObject("InternetExplorer.Application") '*** Détermine l’emplacement du fichier *.htm à afficher *****' Set objSH = WScript.CreateObject("WScript.Shell") Chemin = objSH.CurrentDirectory & "\" '********* Attend que Internet Explorer s’affiche Do While objIE.Busy WScript.Sleep 200 Loop '************** Charge le document *.htm objIE.Navigate Chemin & "fichier.htm" objIE.Visible = True **********' *******************' Votre fichier Html s’affiche alors. Cependant, la valeur de certaines zones de texte peuvent être spécifiées par le script lui-même : le nom de l’utilisateur, le nom du poste, la date de la demande et l’heure de celle-ci. Il est possible d’accéder au contenu d’une zone de texte par le biais de la propriété value de l’objet en précisant ce dernier avec son nom tel que vous l’avez spécifié à l’aide de l’attribut Name au sein du document Html. Ainsi, les dernières lignes du code précédent deviendraient celles-ci : '************** Charge le document *.htm objIE.Navigate Chemin & "fichier.htm" *******************' Set objNT = WScript.CreateObject("WScript.Network") objIE.Document.frm.txtPoste.value = objNT.ComputerName objIE.Document.frm.txtUtilisateur.value = objNT.UserName objIE.Document.frm.txtDate.value = Date() objIE.Document.frm.txtHeure.value = Time() objIE.Visible = True DescoDev 5. Techniques avancées de Script 109 Spécifier les attributs d’affichage du formulaire Html Il est possible au script de spécifier différents attributs de l’affichage de la page web servant de formulaire de saisie tels que la largeur, la hauteur, la position et autres attributs esthétiques. Vous pouvez spécifiez la position et les dimensions de la fenêtre d’Internet Explorer en accédant à différentes propriétés de l’instance de celui-ci : Propriété Description Height Hauteur de la fenêtre. Minimum 100 pixels. Left Position de la gauche de la fenêtre. Top Position du haut de la fenêtre. Width Largeur de la fenêtre. Minimum 100 pixels. Notez que les coordonnées et dimensions sont spécifiées en pixels. Set objIE = WScript.CreateObject("InternetExplorer.Application") objIE.Width = 550 objIE.Height = 550 objIE.Left = 100 objIE.Top = 100 objIE.Visible = True Les autres attributs disponibles permettent de spécifier si la barre d’outils standard du navigateur doit être affichée, la barre d’état, la barre de menu, etc. Les valeurs possibles sont False ou True ou encore 0 et 1. Propriété Description MenuBar Spécifie si la barre de menu doit être affichée. ToolBar Spécifie si la barre d’outils doit être affichée. StatusBar Spécifie si la barre d’état doit être affichée. Spécifie si la fenêtre peut être dimensionnée. Semble évidemment causer des problèmes d’affichage lorsque appliqué sur Internet Explorer 6.0 et les versions antérieures. Resizable Set objIE = WScript.CreateObject("InternetExplorer.Application") objIE.StatusBar = False objIE.MenuBar = False objIE.ToolBar = False objIE.Visible = True DescoDev 5. Techniques avancées de Script 110 Accéder aux variables définies au sein de la page Html Les pages Html peuvent incorporer du script VBScript tel que celui que nous avons utilisé avec Windows Script Host. La différence réside dans le fait que l’hôte est Internet Explorer au lieu d’être WScript.exe et que, conséquemment, les modèles d’objets disponibles ne sont pas les mêmes. Un script est inséré au sein d’une page Html à l’aide de la balise <Script> comme suit: <BODY> <SCRIPT Language="VBScript"> </SCRIPT> </BODY> Ainsi, le code inséré entre les deux balises <Script> sera interprété comme un code VBScript inséré dans un fichier *.vbs. Le but de notre opération est d’y définir une variable qui spécifiera à notre script si l’utilisateur a appuyé sur le bouton ‘Envoyer’ ou non. <BODY> <SCRIPT Language="VBScript"> Public Pret Pret = 0 </SCRIPT> </BODY> ... <TR> <TD ALIGN="Right" ColSpan="2"><P> </P> <A HREF="" onClick="Pret = 1">Envoyer</A> <P> </P> </TD> <TD ColSpan="2"><P> </P> <A HREF="" onClick="Pret = 2">Annuler</A> <P> </P> </TD> </TR> Finalement, nous spécifions la valeur que doit prendre la variable Pret sur le click des différents liens 'Envoyer' et 'Annuler'. Ainsi, notre script attendra que la variable Pret soit différente de zéro et alors il saura que l’utilisateur désire envoyer la demande de service. Notre script WSH devra donc inclure la boucle suivante lui permettant d’attendre le click d’un bouton du formulaire Html avant de continuer son exécution. Souvenez-vous que ces prouesses sont nécessaires puisque les deux applications s’exécutent de manière asynchrone : Do Loop While objIE.Document.Script.Pret = 0 Certains connaisseurs en Html diront peut-être que nous aurions pu utiliser la méthode window.close() intrinsèque au modèle d’objets de Html pour signifier que l’utilisateur désire quitter le formulaire Html mais cette méthode possède le désavantage de détruire l’instance du navigateur. Il est alors impossible à notre script de récupérer les valeurs saisies dans les zones de texte puisque le navigateur n’existe plus. DescoDev 5. Techniques avancées de Script 111 Voici le code complet du script Windows Script Host permettant d’afficher le formulaire Html et d’en attendre les valeurs saisies par l’utilisateur. Les informations sont ensuite envoyées à l’administrateur réseau par le biais de messagerie réseau (net send). Vous devrez changer le destinataire du message indiqué en gras dans le code. Dim objIE, objNT, Texte, Chemin '***** Procède à la création de l’objet Internet Explorer *******' Set objIE = WScript.CreateObject("InternetExplorer.Application") Set objNT = WScript.CreateObject("WScript.Network") '******* Détermine l’emplacement du fichier *.htm à afficher ****' Chemin = objNT.CurrentDirectory() & "\" '************* Attend que Internet Explorer s’affiche Do While objIE.Busy WScript.Sleep 200 Loop *********' '********************* Charge le document *.htm ***************' objIE.Navigate Chemin & "demande service/demande.htm" objIE.Width = 550 objIE.Height = 550 objIE.ToolBar = False objIE.MenuBar = False objIE.StatusBar = False '******************* Rempli les informations connues **********' objIE.Document.frm.txtPoste.value = objNT.ComputerName objIE.Document.frm.txtUtilisateur.value = objNT.UserName objIE.Document.frm.txtDate.value = Date() objIE.Document.frm.txtHeure.value = Time() objIE.Visible = True '********* Attend que l'utilisateur appuie sur un bouton *********' Do WScript.Sleep 100 Loop Until objIE.Document.Script.Pret = 0 '*************** Utilisateur a appuyé sur 'Envoyer' **************' If objIE.Document.Script.Pret = 1 Then Texte = objIE.Document.frm.txtUtilisateur.value _ & " a un problème sur le poste " _ & objIE.Document.frm.txtPoste.value & vbCrLf _ & "Problème: " & objIE.Document.frm.txtProbleme.value & vbCrlf _ & "Gravité: " & objIE.Document.frm.cmbGrave.value CreateObject("WScript.Shell").Run "net send AdminDomaine " & Texte End If objIE.Quit CH06\HTML\Demande Service.vbs DescoDev 5. Techniques avancées de Script 112 Voici l’exemple Recherche.vbs présenté au chapitre précédent qui permet de rechercher les différences occurrences d’un fichier sur le(s) disque(s) du système. Certaines améliorations y ont été apportées. Le script provoque l’affichage d’une page web et y affiche le fichier recherché sur les disques du système ainsi que le répertoire en cours de recherche. Dim objFSO, objDrv, K, Filename, objIE, stResultat, AfficherWeb Set objFSO = WScript.CreateObject("Scripting.FileSystemObject") '********** Récupère le nom de fichier à rechercher On Error Resume Next Filename = WScript.Arguments(0) On Error goto 0 ***************' '***** Si aucun argument spécifié à la ligne de commande **********' If Filename = "" Then Filename = InputBox("Entrez le nom du fichier à rechercher:") If Filename = "" Then WScript.Quit End If End If AfficherPageWeb '********** Parcours les lecteurs du système de A-Z ***************' On Error resume next For K = Asc("a") To Asc("z") If objFSO.DriveExists(Chr(K)) Then Set objDrv = objFSO.GetDrive(chr(k) & ":\") If objDrv.IsReady Then FindFile Filename, objFSO.GetFolder(chr(k) & ":\") End If End If Next '******************* Résultat de la recherche *********************' If Trim(stResultat) <> "" Then MsgBox "Le fichier a été trouvé:" & vbCrLf & vbCrLf & stResultat Else MsgBox "Le fichier n'a pu être trouvé.", vbExclamation End If '************ Dissimule la page web si elle était affichée **********' If AfficherWeb Then objIE.Quit Set objIE = Nothing End If Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 113 Function FindFile( ByVal Filename, ByVal Fld) Dim objFl, stFichier '******* Affiche le répertoire en cours de recherche ***********' If AfficherWeb Then oIE.Document.frm.inp.value = Fld.Path If Right(Fld.Path, 1) = "\" Then stFichier = Fld.Path & Filename Else stFichier = Fld.Path & "\" & Filename End If '*************** Teste l’existence du fichier ******************' If objFSO.FileExists(stFichier) Then stResultat = stResultat & " * " & stFichier & vbCrLf Exit Function End If '********* Récursivité sur l’ensemble des sous-dossiers **********' For Each objFl In Fld.SubFolders FindFile Filename, Fl Next End Function Sub AfficherPageWeb() Dim Chemin If MsgBox("Désirez-vous visualiser le nom des répertoires " _ & "recherchés en cour d'exécution?", vbYesNo) = vbNo Then Exit Sub End If Chemin = CreateObject("WScript.Shell").CurrentDirectory & "\" If objFSO.FileExists(Chemin & "recherche\recherche.htm") Then Set objIE = WScript.CreateObject("InternetExplorer.Application") '*********** Attend que Internet Explorer s’affiche **********' Do While objIE.Busy WScript.Sleep 200 Loop objIE.Navigate Chemin & "recherche\recherche.htm" objIE.Width = 550 objIE.Height = 200 objIE.MenuBar = False objIE.StatusBar = False objIE.ToolBar = False objIE.Document.frm.fichier.value = Filename objIE.Visible = True AfficherWeb = True End If End Sub CH06\HTML\Recherche.vbs DescoDev 5. Techniques avancées de Script 114 Possibilités de WScript.Run La commande Run de l’objet WScript.Shell possède l’avantage de pouvoir exécuter tout logiciel présent sur le système en précisant son chemin mais peut également exécuter toute commande ou logiciel résident aussi simplement qu’il nous est possible de le faire à l’invite de commande DOS. Cette méthode donne donc la possibilité aux scripts Windows Script Host d’étendre leurs capacités. Planifier l’exécution d’un script L’exécution d’un script peut être planifiée en ajoutant celui-ci à la liste de tâches planifiées de Windows. Une tâche planifiée peut être créée à l’aide de l’assistant ou à l’invite de commande à l’aide de la commande AT. Cette commande possède les prototypes suivants : AT [\\ordinateur] [[id] [/DELETE]|/DELETE [/YES]] AT [\\ordinateur] heure [/INTERACTIVE] [/EVERY:date[,...] | /NEXT:date[,...]] "commande" Notez que toute commande de l’invite de commande peut être lancée à l’aide de la méthode Run comme le démontre l’exemple qui suit : Dim WShell, Chemin Chemin = WScript.ScriptFullName Chemin = Left(Chemin, InStrRev(Chemin, "\")) Set WShell = WScript.CreateObject("WScript.Shell") WShell.Run "AT 18:00:00 /interactive " & Chr(34) & chemin _ & "monScript.vbs" & Chr(34) Ainsi, le fichier de script précisé sera automatiquement exécuté tous les jours à 18:00h. Notez que le caractère 34 inséré intentionnellement au début et à la fin du nom et chemin du fichier de script à exécuter représente des guillemets et sert à éviter le plantage du script dans le cas où le chemin du script contiendrait des espaces. Une autre technique aurait été d’insérer quatre guillemets de suite comme suit : WShell.Run "AT 18:00:00 /interactive " & """" & chemin _ & "monScript.vbs" & """" DescoDev 5. Techniques avancées de Script 115 Piloter l’affichage du panneau de configuration Il peut souvent s’avérer utile d’afficher le panneau de configuration afin de permettre à l’utilisateur d’y sélectionner les options de son choix. Quoiqu’aucune commande intrinsèque à Windows Script Host ni à VBScript ne permette une telle prouesse, la méthode Run permet de lancer la commande control.exe qui elle-même demande l’affichage du panneau de configuration. Par exemple, le code suivant provoque l’affichage du calendrier et de la minuterie intégrée dans le panneau de configuration de Windows : Dim WShell Set WShell = CreateObject("WScript.Shell") WShell.Run "control.exe timedate.cpl,,0" Les différents éléments du panneau de configuration sont affichés à l’aide de fichiers *.cpl référençant chacun un des icônes disponibles dans le panneau de configuration. Ensuite, le premier paramètre précédé d’un symbole @ spécifie le panneau à afficher tandis que le second paramètre spécifie l’index de l’onglet sur lequel amener le focus par défaut. Les index des onglets sont précisés à partir de zéro jusqu’au nombre d’onglets moins un. Le tableau suivant décrit l’ensemble des combinaisons permettant l’affichage des différents éléments du panneau de configuration : Module Nom Index Appwiz.cpl - 0à3 Desk.cpl - 0à3 Intl.cpl - 0à4 Main.cpl @0 à @5 0àx MmSys.cpl @0 à @1 0àx SysDm.cpl - 0à3 TimeDate.cpl - 0à1 Description Affiche la boîte de dialogue Ajout/Suppression de programmes. Affiche la boîte de dialogue Affichage. Affiche la boîte de dialogue Paramètres régionaux. Affiche les boîtes de dialogue Souris, Clavier et PCMCIA où le nom représente la boîte de dialogue à afficher. Affiche la boîte de dialogue Sons et multimédia. Affiche la boîte de dialogue Système. Affiche la boîte de dialogue Date/Heure. Exemple Appwiz.cpl,,0 Desk.cpl,,1 Intl.cpl,,2 Main.cpl, @0,1 Main.cpl, mouse,1 Mmsys.cpl, @0,1 Sysdm.cpl,,0 Timedate.cpl,,0 Ainsi, l’exemple suivant aurait pour effet d’afficher la boîte de dialogue permettant à l’utilisateur de sélectionner son écran de veille : Dim WShell Set WShell = WScript.CreateObject("WScript.Shell") WShell.Run "control.exe desk.cpl,,1" DescoDev 5. Techniques avancées de Script 116 Accéder à l’API de Windows à l’aide de RunDll32.exe L’ensembles des fonctionnalités de Windows sont stockées sous forme d’un ensemble de fonctions nommé l’API de Windows. L’API (Application Programming Interface) permet aux programmeurs C/C++, Visual Basic et autres d’accéder à l’ensemble des fonctions qu’utilise luimême le système d’exploitation. Ces fonctions ne peuvent être directement utilisées en Windows Script Host mais le petit exécutable RunDll32.exe nous permet de tricher à ce niveau. RunDll32.exe permet d’exécuter des fonctions emmagasinées au sein de librairies dynamiques en spécifiant le nom du fichier *.DLL contenant la fonction désirée puis le nom de la fonction à exécuter : RunDll32.exe [chemin]\NomLibrairie.dll, NomFonction [Prm1][,PrmN] L’exemple suivant exécute la fonction LockWorkStation contenue au sein de la librairie user32.dll afin de verrouiller la station de travail d’un poste s’exécutant sous Windows 2000. Remarquez qu’il peut s’avérer facultatif de spécifier le chemin complet du fichier *.DLL si ce dernier se trouve dans le répertoire système du poste. Sinon, vous devrez spécifier le chemin complet du fichier. Dim WShell Set WShell = WScript.CreateObject("WScript.Shell") WShell.Run "RunDll32.exe user32.dll, LockWorkStation" Prenez garde à la syntaxe du nom de la fonction à exécuter puisque l’exécution de fonctions API est discriminant à la casse. Ainsi, la fonction lockworkstation n’est pas l’équivalent de la fonction LockWorkStation. Cet autre exemple invoque la boîte de dialogue Copie de disquette à l’aide de la fonction DiskCopyRunDll contenue dans la librairie DiskCopy.dll : Dim WShell Set WShell = WScript.CreateObject("WScript.Shell") WShell.Run "RunDll32.exe DiskCopy.dll, DiskCopyRunDll" Puisqu’il est hors de la prétention du présent document de couvrir l’ensemble des fonctions API du système Windows, les intéressés pourront se référer à l’aide MSDN de Microsoft ou à des livres spécialisés afin d’approfondir le sujet. DescoDev 5. Techniques avancées de Script 117 Thèmes de programmation divers La présente section se veut simplement un ensemble de brèves notions accompagnées de brefs scripts dans le seul but de vous donner des idées et afin de vous encourager à approfondir votre découverte de Windows Script Host. Cependant, aucune véritable nouveauté ne sera abordée au sein de cette section et tous les codes utiliseront des éléments que vous avez préalablement acquis au long du présent ouvrage. Les codes qui suivent ont simplement la prétention de vous faire découvrir divers modèles d’objets intrinsèques à la plupart des systèmes Windows. Envoyer des courriers électroniques simples avec CDONTS L’envoi de courriers électroniques s’effectue très simplement à l’aide des objets exposés par la librairie CDONTS.DLL retrouvée sur l’ensemble des systèmes Windows 2000. Si votre système ne possède pas la librairie nécessaire, copiez-la sur votre disque dur à partir du CD-Rom d’accompagnement à partir du répertoire \Librairies\. Installez préférablement cette librairie au sein du répertoire système (system ou system32) de votre poste. Ensuite, souvenez-vous que vous devrez inscrire cette librairie auprès de la base de registres comme suit : RegSvr32.exe c:\winnt\system32\cdonts.dll La librairie CDONTS (Collaborative Data Objects for NT Services) permet d’envoyer des courriers électroniques le plus simplement du monde. Puisque vous faites face à un nouveau modèle d’objets, examinez d’abord les objets exposés par la librairie. Une Session établie par un utilisateur sur son compte de message peut posséder un Inbox et un Outbox. Chacun de ces dossiers possèdent une collection Messages contenant des objets de type Message. Chacun de ces messages, en envoi ou en entrée, peut posséder des Attachments ou des Recipients correspondant au(x) récipiendaire(s) du message. L’objet NewMail, quant à lui, représente un courrier électronique n’étant pas associé ni à la boîte de réception de l’utilisateur ni à sa boîte d’envoi. Les scripts suivants utilisent les objets CDONTS qui ne sont accessibles que sous Windows 2000 et 2003. Les scripts suivants ne peuvent donc pas s’exécuter sous Windows 98 ou Windows XP. Créez d’abord une référence sur l’objet NewMail afin de procéder à la création d’un message électronique comme suit : Dim Msg Set Msg = WScript.CreateObject("CDONTS.NewMail") DescoDev 5. Techniques avancées de Script 118 L’objet NewMail possède les propriétés et méthodes suivantes : Propriété Description Spécifie la ou les adresse(s) destination en tant que copie conforme invisible du message. Spécifiez-y des adresses valides ([email protected]). Bcc Différentes destinations peuvent être précisées en les séparant par des points-virgules. Spécifie le message même du courrier. Insérez-y des balises Html seulement Body si BodyFormat = CdoBodyFormatHTML. Spécifie le format du message du courrier où CdoBodyFormatHtml = 0 et CdoBodyFormatText = 1. Si le format du message utilise Html, les BodyFormat balises Html insérées au sein du message seront interprétées au lieu d’être affichées textuellement comme lorsque le format utilise Text. Spécifie la ou les adresse(s) destination en tant que copie conforme du message. Spécifiez-y des adresses valides ([email protected]). Cc Différentes destinations peuvent être précisées en les séparant par des points-virgules. URL complet de base du message et de ses attachements. Cet URL est ContentBase utilisé pour ensuite insérer des éléments (images, fichiers) référencés à l’aide d’une adresse relative. ContentLocation URL complet du message et de ses attachements. Spécifie l’adresse de provenance du message. Spécifiez-y une adresse de From messagerie valide ([email protected]). Spécifie l’importance du courrier où Low=0, Normal=1 et High=2. Importance MailFormat Subject Spécifie le format du courrier où CdoMailFormatMime = 0 et CdoMailFormatText = 1. Value Spécifie l’objet, le sujet, le titre du message. Spécifie la ou les adresse(s) destination du message. Spécifiez-y des adresses de messagerie valides ([email protected]). Différentes destinations peuvent être précisées en les séparant par des points-virgules. Spécifie la valeur arbitraire d’un entête Http à insérer au sein du message. Méthode Description AttachFile Ajoute un fichier attaché au courrier. AttachURL Ajoute un fichier attaché au courrier en tant que lien URL. Send Lance l’envoi du message. SetLocaleIDs Spécifie l’identificateur CodePage utilisé au sein du courrier. To La méthode Send demeure la technique la plus simple pour envoyer un courrier électronique. Cette méthode supporte plusieurs paramètres facultatifs permettant de préciser la source du courrier, sa destination, son message, son sujet, etc. NewMail.Send [From][,To][,Subject][,Body][,Importance] Notez que l’ensemble des paramètres sont insérés entre crochets et sont donc facultatifs. Examinez à la page suivante un code utilisant la méthode Send pour envoyer un courrier. DescoDev 5. Techniques avancées de Script 119 '****************************************************************' '* Ce code effectue la sauvegarde d’un répertoire et envoi un *' '* courrier électronique lorsque celle-ci est complétée. *' '****************************************************************' Dim FSO, Msg Dim StSujet, StMsg Set FSO = WScript.CreateObject("Scripting.FileSystemObject") Set Msg = WScript.CreateObject("CDONTS.NewMail") On Error Resume Next FSO.CopyFolder "c:\inetpub\*", "d:\Backup\inetpub\" '****************************************************************' '* Défini le message selon s’il y a eu erreur ou non *' '****************************************************************' If Err.Number Then StSujet = "Échec de la sauvegarde" StMsg = Err.Description Else StSujet = "Réussite de la sauvegarde" StMsg = "La sauvegarde s’est complétée le " & Now() End If '****************************************************************' '* Lance l’envoi du message *' '****************************************************************' Msg.Send "[email protected]", "[email protected]", StSujet, StMsg Une autre façon de faire demeure de préciser les valeurs pour chacune des propriétés indispensables de l’objet NewMail avant d’invoquer la méthode Send sans préciser aucun paramètre. Cette technique nécessite un plus grand nombre de lignes de code mais présente l’avantage d’être plus aisément lisible et compréhensible. If Err.Number Then Msg.Subject = "Échec de la sauvegarde" Msg.Body = Err.Description Else Msg.Subject = "Réussite de la sauvegarde" Msg.Body = "La sauvegarde s’est complétée le " & Now() End If Msg.To = "[email protected]" Msg.From = "[email protected]" '****************************************************************' '* Lance l’envoi du message *' '****************************************************************' Msg.Send DescoDev 5. Techniques avancées de Script 120 Manipuler une base de registres à distance Les objets intrinsèques à Windows Script Host ne prennent pas en charge la manipulation de registre à distance. Par contre, la librairie RegObj.dll expose les objets nécessaires à ces opérations. Si votre système ne possède pas la librairie, copiez-la sur votre disque dur à partir du CD-Rom d’accompagnement à partir du répertoire \Librairies\. Installez préférablement cette librairie au sein du répertoire système (system ou system32) de votre poste. Ensuite, souvenez-vous que vous devrez inscrire cette librairie auprès de la base de registres comme suit : RegSvr32.exe c:\winnt\system32\regobj.dll La librairie RegObj.dll expose trois objets principaux qui sont les suivants : Objet Registry RegKey RegValue Description Objet global permettant l’accès à une base de registres et aux fonctionnalités permettant de créer une instance d’un objet Registry distant. Représente une clé dans la base de registres et possède une collection de sous-clés contenant également des objets de type RegKey. Représente une valeur au sein d’une clé de la base de registres. La valeur peut être de type Binary, DWord, String, etc. Pour manipuler la base de registres d’un ordinateur distant, créez d’abord une référence sur l’objet global Registry comme suit : Dim objReg Set objReg = WScript.CreateObject("RegObj.Registry") Une fois que vous possédez une référence sur une instance de l’objet global de la librairie RegObj, vous pouvez utiliser la méthode RemoteRegistry afin d’obtenir une autre référence sur un nouvel objet Registry en spécifiant le nom du poste que vous désirez connecter sous forme de chemin UNC. Notez que vous devez évidemment posséder les permissions NT nécessaires pour connecter la base de registres de l’ordinateur spécifié. Dim objReg, objDst Set objReg = WScript.CreateObject("RegObj.Registry") Set objDst = objReg.RemoteRegistry("\\NomPoste") L’objet Registry ainsi obtenu permettra désormais d’obtenir une référence sur une clé de la base de registres connectée à l’aide de l’une des méthodes parmi celles exposées par l’objet. Méthode Description AddRootRegKey Permet d’ajouter un alias vers une clé de base HKEY_. Obtient un objet RegKey à partir d’une clé de base HKEY_ ou à partir d’un pointeur de structure (Handle) fourni par l’API de Windows. RegKeyFromString Obtient un objet RegKey à partir du chemin de la clé à connecter. RegKeyFromHKey RemoteRegistry Obtient un objet Registry sur le registre du poste distant spécifié. DescoDev 5. Techniques avancées de Script 121 L’exemple suivant permet d’obtenir un objet RegKey représentant la clé de registre HKEY_USERS\.DEFAULT\Control Panel\Desktop contenant les différentes valeurs des configurations d’affichage (schémas de couleurs, image de fond, etc) des utilisateurs du poste connecté. Dim objReg, objDst, objKey Set objReg = WScript.CreateObject("RegObj.Registry") Set objDst = objReg.RemoteRegistry("\\NomPoste") Set objKey = objDst.RegKeyFromString("\HKEY_USERS\.DEFAULT\" _ & "Control Panel\Desktop") Finalement, les différentes valeurs contenues au sein d’une clé du registre peuvent être obtenues à l’aide de la collection RegValues tandis que la valeur par défaut de la clé peut être obtenue à l’aide de la propriété RegValue. L’ensemble des sous-clés sont quant à elles obtenues à l’aide de la collection SubKeys. Voici la liste des membres de l’objet RegKey : Propriété Description FullName Nom pleinement qualifié de la clé de registre référencée. Obtient le pointeur de structure (Handle) de la clé référencée. Cette valeur n’est utilisable qu’au sein de l’API de Windows. Nom de la clé de registre référencée. HKey Name Obtient un objet RegKey représentant la clé parent de la clé référencée. Retourne NULL lorsque la clé est une clé HKEY_ de premier niveau. Parent SubKeys Value Values Méthode ParseKeyName Obtient une collection des sous-clés de la clé actuellement référencée. Obtient ou détermine les données de la valeur par défaut sous forme de chaîne de caractères. Obtient une collection d’objets RegValue contenues par la clé référencée. Description Traite une chaîne de caractères contenant le nom pleinement qualifié d’une clé de registre et en retourne un objet RegKey correspondant. L’ensemble des valeurs de la clé créée dans l’exemple précédant peut donc être récupéré et affiché comme suit : Dim objReg, objDst, objKey, objVal Set objReg = WScript.CreateObject("RegObj.Registry") Set objDst = objReg.RemoteRegistry("\\NomPoste") Set objKey = objDst.RegKeyFromString("\HKEY_USERS\.DEFAULT\" _ & "Control Panel\Desktop") For Each objVal In objKey.Values MsgBox objVal.Name & " a la valeur " & CStr(objVal.Value) Next CH06\Liste RegValues.vbs DescoDev 5. Techniques avancées de Script 122 Voici la liste des membres de l’objet RegValue : Propriété Name Type Value Description Nom de la valeur sous forme de chaîne de caractères. Vaut "" lorsque la valeur référencée est la valeur par défaut. Type de donnée de la valeur où rvNone = 0, rvString = 1, rvExpandString= 2, rvBinary = 3, rvLong = 4 et rvMultiString = 7. Donnée de la valeur sous forme de variant. Utilisez la conversion explicite avant utilisation afin d’éviter les erreurs. Méthode Description ChangeType Change le type de données d’une valeur en un autre type de données. Comme le démontre l’exemple suivant, il est possible d’obtenir une référence sur une valeur spécifique en précisant le nom de la valeur à la collection Values de l’objet RegKey. Le script suivant obtient le chemin du fond d’écran par défaut pour l’ensemble des utilisateurs d’un poste distant. Dim objReg, objDst, objKey, objVal Set objReg = WScript.CreateObject("RegObj.Registry") '***************************************************************' '* Modifiez le nom du poste à connecter (sous forme de UNC). *' '***************************************************************' Set objDst = objReg.RemoteRegistry("\\NomPoste") '***************************************************************' '* Spécifie la clé de registre à référencer. *' '***************************************************************' Set objKey = objDst.RegKeyFromString("\HKEY_USERS\.DEFAULT\" _ & "Control Panel\Desktop") '***************************************************************' '* Obtient la donnée de la valeur Wallpaper. *' '***************************************************************' Set objVal = objKey.Values("Wallpaper") MsgBox "Fond d’écran : " & CStr(objVal.Value) CH06\RegObj FondEcran.vbs Les systèmes Windows 95/98 ne supportent pas l’accès distant à leur base de registres par défaut. Pour que ces systèmes prennent en charge ces fonctionnalités, il est d’abord nécessaire d’y installer le composant optionnel Remote Registry. DescoDev 5. Techniques avancées de Script 123 Récupérer les configurations matérielles d’un poste avec WMI WMI (Windows Management Instrumentation) est un modèle d’objets disponibles sous les systèmes Windows utilisant la technologie NT qui permet de connecter des postes distants dans le but d’y effectuer diverses opérations. La connexion à des postes distants s’effectue très simplement à l’aide des objets exposés par la librairie wbemdisp.tlb retrouvée sur l’ensemble des systèmes NT. WMI est un modèle d’objets suffisamment complet pour le qualifier de modèle assez complexe pour faire l’objet d’un ouvrage à lui seul. Par contre, il est possible de simplifier grandement l’utilisation du modèle en prenant l’objet SWbemLocator pour point de départ commun à tout script utilisant WMI. L’objet SWbemLocator permet de connecter le poste local ou un poste distant afin d’y activer les fonctionnalités WMI. Dim objLoc Set objLoc = WScript.CreateObject("WbemScripting.SWbemLocator") L’objet SWbemLocator possède une méthode ConnectServer permettant de connecter un poste et la propriété Security_, référence vers un objet de type WbemSecurity que nous n’étudierons pas dans le cadre du présent ouvrage. La méthode ConnectServer attend que le script spécifie le nom NetBIOS ou adresse IP du poste à connecter, nom d’utilisateur et mot de passe à utiliser pour la connexion, etc. et retourne en échange un objet de type WbemServices représentant le service WMI s’exécutant sur le poste distant spécifié. Cet objet sera celui que votre script devra utiliser afin de récupérer les configurations logicielles du poste distant donc conservez-en jalousement la référence. Dim objLoc, objSvc Set objLoc = WScript.CreateObject("WbemScripting.SWbemLocator") Set objSvc = objLoc.ConnectServer("nomPoste", , "admin", "12345") Quoique l’objet WbemServices prévoie une pluralité de méthodes et de propriétés, nous n’utiliserons que sa méthode InstancesOf permettant d’obtenir une instance d’une classe de programmation WMI afin d’ultérieurement la piloter. Les classes sont obtenues en spécifiant une chaîne de caractères unique correspondant à un élément logiciel ou matériel du système connecté. L’exemple suivant récupère la liste des lecteurs de disquettes d’un poste distant : Dim objLoc, objSvc, objFloppy Set objLoc = WScript.CreateObject("WbemScripting.SWbemLocator") Set objSvc = objLoc.ConnectServer("nomPoste", , "admin", "12345") Set objFloppy = objSvc.InstancesOf("Win32_FloppyDrive") L’objet retourné par l’utilisation de la méthode InstancesOf est de type SWbemObjectSet et représente un ensemble d’éléments correspondants à la classe demandée, classe Win32_FloppyDrive dans l’exemple qui nous concerne. Cet objet agi donc sous la forme d’une collection et peut conséquemment posséder une référence sur plusieurs objets qu’il suffit de parcourir afin d’en obtenir la liste complète. Par contre, prenez garde que chacun des éléments de cette collection possède des propriétés et des méthodes différentes les un des autres selon la classe invoquée. DescoDev 5. Techniques avancées de Script 124 Dans le cas d’un objet répondant à la classe Win32_FloppyDrive, il est possible d’accéder aux membres Manufacturer, Status, DeviceID et ConfigManagerErrorCode comme suit : Dim objLoc, objSvc, objFloppy, objInst, stMsg Set objLoc = WScript.CreateObject("WbemScripting.SWbemLocator") Set objSvc = objLoc.ConnectServer("nomPoste", , "admin", "12345") Set objFloppy = objSvc.InstancesOf("Win32_FloppyDrive") For Each objInst In objFloppy stMsg = Trim(objInst.Manufacturer) stMsg = stMsg & vbCrLf & LCase(Trim(objInst.status)) = "ok" stMsg = Trim(objInst.DeviceID) MsgBox stMsg, vbInformation, "Floppy Drive" Next Voici la liste non exhaustive des principales classes d’accès au matériel de postes exécutant Windows et WMI : Classe Description Win32_BaseBoard Obtient la description de la carte-mère du poste. Win32_Battery Obtient la description de(s) batterie(s) de sauvegarde (UPS). Win32_CDRomDrive Obtient la description de(s) lecteur(s)/graveur(s) de CD et DVD. Win32_DesktopMonitor Obtient la description de(s) moniteur(s) relié(s) au poste. Win32_DiskDrive Obtient la description de(s) disque(s) dur(s) relié(s) au poste. Win32_DiskPartition Obtient la description de(s) partition(s) relié(s) au disque spécifié. Win32_Keyboard Win32_Network Adapter Win32_Operating System Win32_Physical Memory Obtient la description du clavier relié au poste. Obtient la description de(s) carte(s) réseau reliée(s) au poste. Obtient la description de(s) moniteur(s) relié(s) au poste. Obtient la description de la mémoire vive reliée au poste. Win32_Printer Obtient la description de(s) appareils de pointage relié(s) au poste (souris, stylet, etc). Obtient la description de(s) imprimante(s) reliée(s) au poste. Win32_Processor Obtient la description de(s) processeur(s) relié(s) au poste. Win32_Share Obtient la description de(s) partage(s) disponible(s) sur le poste. Win32_PointingDevice Win32_VideoController Obtient la description de(s) carte(s) vidéo reliée(s) au poste. DescoDev 5. Techniques avancées de Script 125 L’exemple complet qui suit invite l’utilisateur à saisir le nom NetBIOS ou l’adresse IP d’un poste qu’il désire connecter. Ensuite, le script établi une connexion WMI et en retire plusieurs informations concernant la configuration matériel avant de l’inscrire dans un fichier texte créé à la racine du disque C:\ . Dim FSO, Fichier, Machine, StMachineName '********************** Nom de la machine ***************************' StMachineName = InputBox("Entrez le nom de la machine à connecter.") If StMachineName = "" Then WScript.Quit '******************** Connexion à la machine ************************' Set Machine = Connecter(StMachineName) 'Fonction Connecter() plus bas If Machine Is Nothing Then WScript.Quit '********************* Ouverture du fichier *************************' Set FSO = CreateObject("Scripting.FileSystemObject") Set Fichier = FSO.CreateTextFile("c:\" & stMachineName & ".txt", True) Fichier.WriteLine("INVENTAIRE DE " & UCase(StMachineName)) Fichier.WriteLine("====================================") '************************** DetectCPU Machine Fichier.WriteLine(" ") Détection ******************************' DetectMotherboard Machine Fichier.WriteLine(" ") 'Les fonctions Detect??? plus bas DetectRAM Machine Fichier.WriteLine(" ") DetectHDD Machine Fichier.WriteLine(" ") DetectCDROM Machine Fichier.WriteLine(" ") DetectVideo Machine Fichier.WriteLine(" ") DetectAudio Machine Fichier.WriteLine(" ") DetectNet Machine Fichier.WriteLine(" ") DetectMouse Machine Fichier.WriteLine(" ") '******* Fermeture du fichier et MsgBox pour signaler la fin *********' Fichier.Close MsgBox "La détection est terminée sur " & StMachineName Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 126 Function Connecter(ByVal MachineName) Dim objLocator, ObjService On Error Resume Next '************** Création de l'objet Locator ********************' Set objLocator = CreateObject("WbemScripting.SWbemLocator") If Err.Number Then MsgBox "Une erreur est survenue lors de la création de Locator." Err.Clear Exit Function End If '*********** Connexion à la machine MachineName ****************' Set ObjService = objLocator.ConnectServer(MachineName) ObjService.Security_.ImpersonationLevel = 3 'Impersonate If Err.Number Then MsgBox "Une erreur est survenue lors de la connexion." Err.Clear End If Set Connecter = ObjService End Function '*********************************************************************' Function DetectCDROM(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_CDRomDrive") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("LECTEURS CDROM\DVDROM") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Manuf: " & Trim(objInst.Manufacturer)) Fichier.WriteLine("Descr: " & Trim(objInst.Description)) Fichier.WriteLine("DeviceID: " & Trim(objInst.DeviceID)) Fichier.WriteLine(" ") Next DetectCDROM = N End Function Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 127 Function DetectAudio(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_SoundDevice") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("ADAPTEURS AUDIO") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Produit: " & Trim(objInst.ProductName)) Fichier.WriteLine("DeviceID: " & Trim(objInst.PNPDeviceID)) Next DetectAudio = N End Function '*********************************************************************' Function DetectNet(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_NetworkAdapter") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("CARTE-RÉSEAU") Fichier.WriteLine("====================================") For Each objInst In objSet St = LCase(Trim(objInst.Name)) If InStr(St, "miniport") <= 0 Then If InStr(St, "ras async adapter") <= 0 And _ InStr(St, "carte asynchrone ras") <= 0 And _ InStr(St, "parallèle direct") <= 0 And _ InStr(St, "direct parallel") <= 0 Then N = N + 1 Fichier.WriteLine(Trim(objInst.ProductName & "")) Fichier.WriteLine(" ") End If End If Next DetectNet = N End Function Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 128 Function DetectCPU(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_Processor") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("PROCESSEUR") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Produit: " & Trim(objInst.Name) & " " _ & Trim(objInst.CurrentClockSpeed) & "MHz") Next DetectCPU = N End Function '*********************************************************************' Function DetectMotherboard(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_BaseBoard") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("CARTE-MÈRE") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Produit: " & Trim(objInst.Manufacturer) _ & " " & Trim(objInst.Product) & " " & Trim(objInst.Version)) Next DetectMotherboard = N End Function Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 129 Function DetectHDD(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_DiskDrive") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("DISQUE DUR") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Produit: " & Trim(objInst.Model) & _ " (" & GetGOSize(objInst.Size) & ")") Fichier.WriteLine(" ") Next DetectHDD = N End Function '*********************************************************************' Function DetectMouse(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_PointingDevice") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("SOURIS") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Fichier.WriteLine("Produit: " & Trim(objInst.Name) & _ " (" & Trim(objInst.NumberOfButtons) & " boutons)") Fichier.WriteLine(" ") Next DetectMouse = N End Function Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 130 Function DetectVideo(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_VideoController") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("====================================") Fichier.WriteLine("ADAPTEURS VIDÉO") Fichier.WriteLine("====================================") For Each objInst In objSet N = N + 1 Select Case objInst.VideoArchitecture Case 3 'CGA St = "(CGA" Case 4 'EGA St = "(EGA" Case 5 'VGA St = "(VGA" Case 6 'SVGA St = "(SVGA" Case 7 'MDA St = "(MDA" Case 8 'HGC St = "(HGC" Case 9 'MCGA St = "(MCGA" Case 10 '8514A St = "(8514A" Case 11 'XGA St = "(XGA" Case 12 'Linear Frame Buffer St = "(Linear Frame Buffer" Case 13 'PC-98 St = "(PC-98" End Select Select Case objInst.AcceleratorCapabilities Case 2 St = St & "/Graphic Accelerator)" Case 3 St = St & "/3D Accelerator)" Case Else St = St & ")" End Select Fichier.WriteLine("Produit: " & Trim(objInst.Caption) & St) Fichier.WriteLine("DeviceID: " & Trim(objInst.PNPDeviceID)) Next DetectVideo = N End Function Le code se poursuit sur la page suivante DescoDev 5. Techniques avancées de Script 131 Function DetectRAM(ByRef ObjService) Dim objFileSystem, objSet, obj, objInst, N On Error Resume Next Set objSet = ObjService.InstancesOf("Win32_PhysicalMemory") If objSet.Count = 0 Then Exit Function Fichier.WriteLine("MÉMOIRE RAM") For Each objInst In objSet N = N + 1 Select Case Trim(objInst.MemoryType & "") Case "3", "4", "5" St = "DRAM" Case "6" St = "EDO" Case "7" St = "EDRAM" Case "8" St = "VRAM" Case "9" St = "SRAM" Case "10" St = "RAM" Case "11" St = "ROM" Case "12" St = "Flash" Case "13", "14", "15" St = "EPROM" Case "16" St = "CDRAM" Case "17", "18", "19" St = "SDRAM" End Select Fichier.WriteLine("Mémoire: " & St) St = GetGOSize(Trim(objInst.Capacity)) Mm = CLng(Left(St, Len(St) - 2)) If CLng(Mm) <= 10 Then Mm = 8 ElseIf Mm <= 21 Then Mm = 16 ElseIf Mm <= 45 Then Mm = 32 ElseIf Mm <= 110 Then Mm = 64 ElseIf Mm <= 170 Then Mm = 128 ElseIf Mm <= 290 Then Mm = 256 ElseIf Mm <= 600 Then Mm = 512 End If Fichier.WriteLine("Capacité: " & Mm & " Mo") Fichier.WriteLine("Emplac.: " & Trim(objInst.DeviceLocator)) Next DetectRAM = N End Function DescoDev 5. Techniques avancées de Script 132 Function GetGOSize(ByVal Sz) Dim tmpSz tmpSz = CDbl(Left(Sz, Len(Sz) - 3)) If CDbl(tmpSz / 1024) > 1000 Then GetGOSize = FormatNumber(CStr((tmpSz / 1024) / 1024), 2) & "Go" Else GetGOSize = FormatNumber(CStr(tmpSz / 1024), 2) & "Mo" End If End Function CH05\Inventaire.vbs Vous aurez probablement remarqué que l’ensemble des fonctions Detect??? travaillent de manière similaire : elles utilisent un objet WbemServices obtenu par le truchement de l’exécution de la fonction Connecter et représentant une connexion WMI sur le poste distant spécifié par l’utilisateur et s’en servent afin d’interroger une classe de matériel spécifique (Win32_PhysicalMemory, Win32_DiskDrive, etc). Les informations obtenues à l’aide de la méthode InstancesOf sont ensuite inscrites au sein du fichier Fichier créé au sein du module principal du code. Vous remarquerez que l’ensemble des classes WMI utilisées possèdent des propriétés qui peuvent différer de l’une à l’autre. Classe Propriétés Win32_BaseBoard ConfigOptions, HotSwappable, Manufacturer, Product, Version, etc. Win32_Battery BatteryRechargeTime, BatterieStatus, Manufacturer, Name, etc. Win32_CDRomDrive Description, DeviceID, Drive, Manufacturer, etc. Win32_DesktopMonitor Bandwidth, DeviceID, DisplayType, MonitorType, Name, etc. Win32_DiskDrive BytesPerSector, InterfaceType, Model, Partitions, Size, TotalSectors Win32_DiskPartition Bootable, BootPartition, DeviceID, DiskIndex, PrimaryPartition, Size Win32_Keyboard Win32_Network Adapter Win32_Physical Memory Win32_PointingDevice DeviceID, IsLocked, Layout, NumberOfFunctionKeys, etc. Win32_Printer Capabilities, DefaultPriority, Description, DriverName, etc. Win32_Processor Architecture, Name, CurrentClockSpeed, L2CacheSize, etc. Win32_SoundDevice DMABufferSize, MPU401Address, ProductName, PNPDeviceID, etc. AdapterType, Description, Name, ProductName Capacity, DeviceLocator, MACAddress, MemoryType DeviceInterface, Name, NumberOfButtons, PointingType, etc. Win32_VideoController AcceleratorCapabilities, Caption, PNPDeviceID, VideoArchitecture, etc DescoDev