Inventaire des Service Packs Windows XP - Première partie

Paru le 15/03/2005

Par Les Messieurs Script de Microsoft

Le Docteur Scripto au travail

Attentifs aux demandes d'un public toujours fidèle, les Messieurs Script ont décidé de lancer une nouvelle rubrique consacrée aux talents de notre Monsieur Script virtuel, Dr. Scripto. Vous l'avez déjà entendu chanter ou raconter des blagues plutôt mauvaises, maintenant, découvrez le côté très technique de ce petit bonhomme en blouse blanche. Parcourez avec lui son immense entrepôt virtuel de scripts et d'astuces rangés dans l'un des bureaux de notre superbe appartement du campus Microsoft à Redmond.

Le magasin de scripts du Docteur Scripto abordera les problèmes de script liés à l'administration du système, souvent tirés des expériences de nos lecteurs, et développera des scripts pour les résoudre. La plupart des exemples du référentiel de scripts exécutent une seule tâche, assez simple. Dans cette rubrique, en revanche, nous rassemblerons différents éléments afin d'obtenir des scripts plus complexes. Ces scripts ne seront ni complets ni infaillibles. Ils vous montreront toutefois la marche à suivre pour créer des scripts à partir de modules de code réutilisables, gérer des erreurs et des codes de retour, obtenir des entrées et des sorties à partir de différentes sources, exécuter des scripts sur plusieurs ordinateurs, et effectuer d'autres opérations avec vos scripts de production.

La plupart des sujets abordés dans cette rubrique impliqueront l'utilisation de techniques de script intermédiaires à avancées. Nous essaierons de les expliquer clairement et, comme toujours, de permettre à tous nos lecteurs de les appréhender. Nous espérons que ces articles et scripts vous seront utiles – faites-nous part de votre avis, des solutions que vous proposez pour ces problèmes et des sujets que vous souhaiteriez voir publiés.

Sommaire,Sur cette page

Inventaire des Service Packs Windows XP – Première partie
Inventaire des réseaux n'utilisant pas Active Directory
Obtention d'une liste d'ordinateurs à partir d'un fichier texte
Récupération de la version du système d'exploitation et du Service Pack
Tri des ordinateurs par Service Pack
Envoi des données à un fichier texte
La pièce montée
Pour en savoir plus

Inventaire des Service Packs Windows XP – Première partie

Le 12 avril 2005 est imminent. Ce n'est pas un jour férié (il peut l'être quelque part, mais dans la mesure où nous travaillons aujourd'hui, pour nous, il ne l'est pas), mais il revêt une certaine importance. Il ressemble à un mardi ordinaire sur la plupart des calendriers, mais pour les administrateurs système chargés de la gestion des clients Windows XP, c'est un jour décisif.

En effet, à partir du 12 avril, vous ne pourrez plus désactiver la remise du Service Pack 2 Windows XP dans les services Mises à jour automatiques et Windows Update (pour plus de détails, consultez la page Temporarily Disabling Delivery of Windows XP Service Pack 2 Through Windows Update and Automatic Updates site en anglais
[en anglais]). Pour le moment, vous pouvez empêcher le service des mises à jour automatiques de télécharger automatiquement le Service Pack 2 sur les clients Windows XP en définissant une valeur dans le Registre. Cette procédure est décrite en détail dans le document Block Windows XP Service Pack 2 site en anglais (en anglais).

À partir du 12 avril, ce paramètre du Registre sera ignoré. Ou, pour reprendre les termes de Madame de Pompadour (maîtresse et administrateur système de Louis XV), « Après nous, le Service Pack 2 ».

En ce qui concerne les scripteurs, le 12 avril marque le début d'un « jeu »! Cette date constitue une excellente opportunité de montrer à quel point la création de scripts peut s'avérer utile dans la gestion d'une mise à niveau de masse potentiellement complexe. Et, croyez-moi, le Docteur Scripto n'a pas laissé passer cette opportunité.

Le gourou des Messieurs Script a fouillé dans sa collection de codes utilisés et recomposés, à la recherche de pièces de choix à assembler afin de créer un script optimal destiné à gérer l'arrivée imminente de SP2.

À présent, regardons la vérité en face : le Service Pack 2 inclut des fonctionnalités utiles destinées à renforcer la sécurité, par exemple le Pare-feu Windows. Cependant, ces mêmes fonctionnalités peuvent compliquer la vie des administrateurs système s'ils ne sont pas en mesure de les gérer. Aussi, les paramètres par défaut du Service Pack 2 verrouillent l'administration à distance avec WMI et ADSI alors que cette fonctionnalité est indispensable pour de nombreux scripts d'administration du système. Nous avons déjà abordé certains de ces problèmes dans des articles et des webcasts précédents, répertoriés à la fin de cet article.

L'idée du sujet traité dans cet article nous est venue de Jeremy, un consultant résidant dans le sud de la Californie, qui nous a envoyé un courrier électronique il y a quelques mois. Il avait installé le Service Pack 2 sur certains clients exécutant Windows XP sur son réseau et voulait écrire un script pour identifier les autres ordinateurs nécessitant une mise à niveau. Nous avons commencé à discuter, et au fur et à mesure certaines idées sont apparues.

Quelle que soit la façon dont votre organisation informatique prévoit de gérer le Service Pack 2, il est certain qu'un inventaire est un bon point de départ. Une fois que vous avez identifié les versions des systèmes d'exploitation et les Service Packs utilisés par les ordinateurs, et que vous connaissez l'étendue du problème, vous avez une idée plus précise de l'impact de cette mise à jour sur vos systèmes et vous êtes en mesure de la gérer de manière adéquate. Vous pourriez, par exemple, échelonner les installations de SP2 afin que votre réseau ne soit pas saturé le 12 avril. Vous pourriez également modifier les paramètres du nouveau pare-feu en fonction des besoins de votre organisation informatique au lieu d'accepter les paramètres par défaut.

Pour vous aider à mener à bien ces opérations, le Dr. Scripto a réuni deux scripts capables de rechercher et d'identifier l'état du Service Pack de tous les clients Windows XP sur différents types de réseaux.

Une fois les spécifications des scripts créées (n'écrivez-vous pas toujours les spécifications avant le code ?), nous nous sommes aperçus que nous aurions besoin d'au moins trois articles pour vous expliquer comment préparer l'installation de Windows XP SP2. Ce premier article vous explique comment dresser l'inventaire des ordinateurs Windows XP d'un groupe de travail ou d'un réseau qui n'utilise pas Active Directory. Dans l'article suivant, nous présenterons des scripts qui remplissent cette même fonction dans Active Directory et qui utilisent à la fois les interfaces ADSI (Active Directory Service Interfaces) et ADO (ActiveX Data Objects). Enfin, pour la « grande finale », nous vous expliquerons comment utiliser l'inventaire qui a permis de déployer le SP2 de sorte que vous puissiez continuer à gérer votre réseau à distance.

Par la suite, cet article sera régulièrement mis à jour et abordera également d'autres sujets relatifs aux scripts.

Inventaire des réseaux n'utilisant pas Active Directory

Pour les débutants, nous allons explorer le scénario le plus simple : la réalisation de l'inventaire d'un réseau qui n'utilise pas Active Directory. Dans ce cas, nous utilisons WMI pour identifier les versions des systèmes d'exploitation et des Service Packs. Cette méthode n'est pas aussi rapide que celles que nous pouvons utiliser avec Active Directory, lesquelles stockent les informations dans l'annuaire et nous permettent ainsi de les récupérer sans avoir à nous connecter à chaque ordinateur. WMI a toutefois l'avantage d'être une technologie utilisée par la plupart des scripteurs Windows, et cette approche convient parfaitement à des réseaux de petite taille.

Dans la mesure où nous n'utilisons pas Active Directory, nous devons fournir au script une liste d'ordinateurs à rechercher. Nous allons utiliser un fichier texte en raison de sa simplicité, mais nous pourrions également utiliser une feuille de calcul ou une base de données. Pour des raisons de symétrie, nous allons également insérer les résultats dans un autre fichier texte.

Obtention d'une liste d'ordinateurs à partir d'un fichier texte

Le Docteur Scripto au travail

Appelons notre fichier texte d'entrée hosts.txt et plaçons un nom d'ordinateur par ligne. Ces ordinateurs doivent être accessibles sur le réseau, et vous devez posséder des privilèges d'administrateur sur eux (comme c'est généralement le cas lorsque vous exécutez un script sur un ordinateur distant). Notre fichier devrait ressembler à celui-ci :

client1
client2
client3
client4

Nous récupérons les noms d'ordinateurs à partir du fichier à l'aide de l'objet FileSystemObject, qui fait partie de Script Runtime (inclus dans l'environnement d'exécution de scripts WSH [Windows Script Host]). Le code ressemble à l'exemple suivant (la plupart d'entre vous doivent le connaître par cœur).

Const FOR_READING = 1
strFilename = "hosts.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextStream = objFSO.OpenTextFile(strFilename, FOR_READING)
Do Until objTextStream.AtEndOfStream
  strComputer = objTextStream.ReadLine
  Wscript.Echo "Use WMI to get OS and SP versions from " & strComputer
Loop

La méthode OpenTextFile de l'objet FileSystemObject nous renvoie en réalité un objet qui représente un flux de texte. Cet objet a des propriétés pratiques telles que AtEndOfStream et des méthodes telles que ReadLine, que nous utilisons ici pour extraire une ligne à la fois.

Récupération de la version du système d'exploitation et du Service Pack

Pour identifier le système d'exploitation et le Service Pack installé sur chaque ordinateur, nous utilisons trois propriétés de la classe WMI Win32_OperatingSystem : Version, ServicePackMajorVersion et ServicePackMinorVersion.

Pour ce faire, nous nous connectons à WMI sur l'ordinateur en question et recherchons les instances de la classe Win32_OperatingSystem. (Cette requête renvoie toujours une seule instance, à savoir, le système d'exploitation en cours d'exécution.) Nous affichons ensuite ces trois propriétés, en concaténant ServicePackMajorVersion et ServicePackMinorVersion, séparés par un point.

'Get strComputer from each line of text file.
Set objWMIService = GetObject("winmgmts://" & strComputer)
Set colOSes = objWMIService.ExecQuery _
 ("SELECT * FROM Win32_OperatingSystem")
For Each objOS in colOSes
  Wscript.Echo
  Wscript.Echo strComputer
  Wscript.Echo "OS Version: " & objOS.Version
  Wscript.Echo "Service Pack: " & objOS.ServicePackMajorVersion & _
   "." & objOS.ServicePackMinorVersion
Next

En exécutant ce code, le résultat est à peu près le suivant.

client1
OS Version: 5.1.2600
Service Pack: 2.0

Pour afficher le nom du système d'exploitation plutôt que le numéro de version, vous devez utiliser la propriété Caption, qui est légèrement plus lisible que la propriété Version. Dans tous les cas, dans ce script, nous ne nous intéressons qu'à Windows XP.

Nous pouvons regrouper les deux composants que nous avons créés et obtenir la version du système d'exploitation et le Service Pack installés sur ces quatre ordinateurs. Voici à quoi devrait ressembler le résultat :

C:\scripts>xpsplist-wmi.vbs 

client1
OS Version: 5.1.2600
Service Pack: 1.0

client2
OS Version: 5.1.2600
Service Pack: 2.0

client3
OS Version: 5.1.2600
Service Pack: 2.0

client4
OS Version: 5.1.2600
Service Pack:

C'est un script WMI simple, et je suis certain que nombre d'entre vous sont en train de bâiller et éprouvent déjà un besoin irrésistible de boire une deuxième tasse de café. Mais cela fait partie de la beauté des technologies de script : une fois que vous les avez apprises, leur utilisation devient facile et habituelle. Dans cet article, nous allons essayer de regrouper les différents éléments qui composent ces technologies, à l'aide de méthodes légèrement plus complexes et pratiques, mais la plupart des éléments de base resteront les mêmes. Souvenez-vous de la philosophie intemporelle du Dr. Scripto : « Soyez fainéants (les responsables informatiques doivent lire « productifs »). Ne réinventez pas la roue ».

Tri des ordinateurs par Service Pack

Le Docteur Scripto au travail

Nous recherchons ici quelque chose de plus complet qu'une simple liste d'ordinateurs accompagnés de la version de leur système d'exploitation et de leur Service Pack. Nous voulons obtenir des résultats triés par Service Pack 2, Service Pack 1 et pas de Service Pack, avec la liste des ordinateurs correspondants. Nous aimerions aussi connaître leur nombre afin d'évaluer l'ampleur de la tâche à l'avance.

Voici le code qui permet d'obtenir ces informations.

'Get strComputer from each line of text file.
Set objWMIService = GetObject("winmgmts://" & strComputer)
Set colOSes = objWMIService.ExecQuery _
 ("SELECT * FROM Win32_OperatingSystem")
For Each objOS in colOSes
  If objOS.Version = "5.1.2600" Then
    If objOS.ServicePackMajorVersion = "2" Then
      strSP2 = strSP2 & strComputer & vbCrLf
      intSP2 = intSP2 + 1
    ElseIf "1" = objOS.ServicePackMajorVersion Then
      strSP1 = strSP1 & strComputer & vbCrLf
      intSP1 = intSP1 + 1
    Else
      strSP0 = strSP0 & strComputer & vbCrLf
      intSP0 = intSP0 + 1
    End If
  Else
    intNotXP = intNotXP + 1
  End If
Next

À présent, nous disposons des noms des ordinateurs qui exécutent chaque Service Pack de Windows XP dans une variable distincte, ainsi que leur nombre. Nous avons également obtenu le nombre d'ordinateurs n'exécutant pas Windows XP grâce un autre compteur.

Si vous souhaitez savoir explicitement si aucun Service Pack n'est installé, utilisez le paramètre ServicePackMajorVersion = 0 (plutôt que Null, contrairement à ce que vous pourriez croire). Nous traitons ici cette probabilité avec la clause Else, qui fonctionne correctement pour l'instant. Si un autre Service Pack était publié à l'avenir, il serait également traité avec la clause Else et comptabilisé comme non-Windows XP. Mais dans le cadre de cet article, nous souhaitons conserver la simplicité de notre code et nous allons laisser de côté la gestion des situations d'urgence à venir.

Envoi des données à un fichier texte

Nous voulons envoyer ces données à un autre fichier texte en utilisant une variation du code qui lit le fichier d'entrée. Cette fois-ci, nous allons vérifier si le fichier nommé existe : si oui, nous l'ouvrons et y ajoutons les données. Dans le cas contraire, nous créons un fichier et y insérons les données. Nous ajoutons une mise en forme très « rétro » au texte brut, ce qui provoque une certaine nostalgie de MS-DOS chez les anciens comme le Dr. Scripto. Notez qu'une fois que nous avons fini d'écrire le flux de texte, nous devons le fermer afin d'enregistrer et de fermer le fichier texte.

Const FOR_APPENDING = 8
strOutputFile = "xpsp.txt"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strOutputFile) Then
  Set objTextStream = objFSO.OpenTextFile(strOutputFile, FOR_APPENDING)
Else
  Set objTextStream = objFSO.CreateTextFile(strOutputFile)
End If

objTextStream.WriteLine "Inventory of Windows XP Service Packs"
objTextStream.WriteLine "Taken " & Now
objTextStream.WriteLine vbCrLf & "Computers Running Windows XP"
objTextStream.WriteLine "============================"
objTextStream.WriteLine  "Total number: " & (intSP2 + intSP1 + intSP0)

objTextStream.WriteLine  vbCrLf & "Service Pack 2"
objTextStream.WriteLine  "--------------"
objTextStream.WriteLine  strSP2
objTextStream.WriteLine  "Total number: " & intSP2

objTextStream.WriteLine  vbCrLf & "Service Pack 1"
objTextStream.WriteLine  "--------------"
objTextStream.WriteLine  strSP1
objTextStream.WriteLine  "Total number: " & intSP1

objTextStream.WriteLine  vbCrLf & "No Service Pack"
objTextStream.WriteLine  "---------------"
objTextStream.WriteLine  strSP0
objTextStream.WriteLine  "Total number: " & intSP0

objTextStream.WriteLine  vbCrLf & "Computers Not Running Windows XP"
objTextStream.WriteLine  "================================"
objTextStream.WriteLine  "Total number: " & intNotXP

objTextStream.WriteLine  vbCrLf & "Could Not Connect To Computer"
objTextStream.WriteLine  "============================="
objTextStream.WriteLine  "Total number: " & intErr
objTextStream.WriteLine

objTextStream.Close

La pièce montée

Maintenant que nous avons enfin rassemblé tout ce dont nous avons besoin, le Dr. Scripto est prêt pour mettre en marche son soudeur à l'arc et son chalumeau oxyacétylénique afin de transformer toutes ces pièces en une machine à inventaires hautes performances ! Bon, d'accord, et si on se contentait d'un script qui s'exécute sur l'ordinateur ? Qu'espériez-vous ?

Nous allons placer les composants déjà mentionnés dans des procédures distinctes afin de les rendre plus modulaires, et faciliter ainsi leur gestion et leur réutilisation. Nous allons accorder une importance particulière à cette démarche dans cette rubrique, car elle constitue un bon moyen de structurer les scripts quelle que soit leur complexité.

Les Messieurs Script n'oublient pas la maxime du Dr. Scripto : « Ne réinventez pas la roue. » Il veut probablement dire par là que nous devrions recycler les codes utiles dans de nombreux scripts. Si telle est votre intention, le fait de placer des fonctionnalités réutilisables dans des sous-routines ou des fonctions que vous pouvez coller dans un script est en fait une stratégie raisonnable. Lorsque vous mettez de tels extraits de code dans un format standard, vous pouvez les réduire à leur version la plus efficace et la plus compacte, et permettre ainsi aux scripteurs de votre organisation de bénéficier de ces améliorations.

Une autre raison qui justifie l'insertion d'une section de code dans une procédure réside dans son utilisation répétée au sein d'un script. Ainsi, vous ne devez écrire le code qu'une seule fois et le conserver à un seul endroit.

Certains d'entre nous trouvent cette procédure longue car les scripts complexes sont plus faciles à lire lorsqu'ils sont divisés en segments. Les Messieurs Script ont longuement débattu sur les vertus des fonctions et des sous-routines, mettant en avant de nombreuses divergences d'opinion. Greg semble penser qu'elles sont surévaluées (nous devrions peut-être le laisser exprimer son point de vue dans un prochain article). Apportez-nous donc votre aide : faites-nous savoir ce qui vous plaît ou vous déplaît dans les procédures et comment vous les utilisez en nous adressant un courrier électronique site en anglais.

D'accord, revenons au script. Nous avons fractionné notre code comme suit :

  • Une routine principale qui initialise les constantes et les variables globales, puis obtient un tableau avec les noms d'ordinateurs via la fonction d'entrée (ReadTextFile) et appelle les autres procédures. La routine principale compte également le nombre d'ordinateurs sur lesquels le script a rencontré une erreur en essayant de se connecter à WMI. Le préfixe « g_ » ajouté aux noms de certaines variables correspond à notre notation des variables globales, dont l'étendue correspond au script dans son intégralité afin qu'elles puissent être utilisées dans plusieurs procédures.

  • Une fonction d'entrée, ReadTextFile, qui prend un nom de fichier comme paramètre et renvoie un tableau avec les noms d'ordinateurs. Le paramètre ReDim Preserve doit alors effectuer le redimensionnement dynamique du tableau pour chaque nouveau nom lu.

  • Une fonction, GetSP, qui réalise l'inventaire et le décompte. Nous lui transmettons le nom de chaque ordinateur pendant que la routine principale passe en revue le tableau. La fonction ajoute le nom d'ordinateur à la liste du Service Pack exécuté par cet ordinateur et incrémente une variable globale qui compte le nombre d'ordinateurs exécutant ce Service Pack. La fonction renvoie un 0 en cas de réussite et un 1 en cas d'erreur.

  • Une sous-routine de sortie, WriteTextFile, qui prend un nom de fichier comme paramètre et écrit les données d'inventaire cumulées dans un fichier texte.

Remarquez que dans la fonction GetSP, nous effectuons un test d'erreur après avoir essayé de nous connecter à WMI sur l'ordinateur distant. L'opération aboutit en présence d'un petit nombre d'ordinateurs, et WMI nous indique s'il n'a pas pu trouver l'ordinateur en question. Lorsque le nombre d'ordinateurs est plus important, nous préférons utiliser la commande ping sur chaque ordinateur afin de nous assurer qu'il est connecté au réseau avant d'essayer de nous connecter à WMI. Quelques lignes de code supplémentaires sont alors nécessaires, mais l'utilisation de la commande ping est plus rapide que d'attendre les délais requis pour WMI.

Enfin, voici le chef d'œuvre du Dr. Scripto :

'List the operating system and service pack of all computers in a text file.
On Error Resume Next

'Initialize constants and variables.
Const FOR_READING = 1
Const FOR_APPENDING = 8
strInputFile = "hosts.txt"
strOutputFile = "xpsp.txt"
g_strSP2 = ""
g_strSP1 = ""
g_strSP0 = ""
g_intSP2 = 0
g_intSP1 = 0
g_intSP0 = 0
g_intNotXP = 0
g_intErr = 0

'Get list of computers from text file.
arrComputers = ReadTextFile(strInputFile)
For Each strComputer In arrComputers
  intGetSP = GetSP(strComputer)
  If 1 = intGetSP Then
    g_intErr = g_intErr + 1
  End If
Next

WriteTextFile(strOutputFile)

WScript.Echo "Data written to " & strOutputFile

'******************************************************************************

'Read text file line by line and return array of lines.
Function ReadTextFile(strFileName)

On Error Resume Next

Dim arrLines()

Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strFilename) Then
  Set objTextStream = objFSO.OpenTextFile(strFilename, FOR_READING)
Else
  WScript.Echo "Input text file " & strFilename & " not found."
  WScript.Quit
End If
Do Until objTextStream.AtEndOfStream
  intLineNo = objTextStream.Line
  ReDim Preserve arrLines(intLineNo - 1)
  arrLines(intLineNo - 1) = objTextStream.ReadLine
Loop
objTextStream.Close
ReadTextFile = arrLines

End Function

'******************************************************************************

'Get list and count of computers by OS and SP.
Function GetSP(strComp)

On Error Resume Next

'Connect to WMI on remote computer.
Set objWMIService = GetObject("winmgmts:\\" & strComp)
If Err <> 0 Then
  WScript.Echo "  Unable to connect to WMI."
  WScript.Echo "    Error Number:" & Err.Number
  WScript.Echo "    Source:" & Err.Source
  WScript.Echo "    Description:" & Err.Description
  GetSP = 1
  Exit Function
End If
Set colOSes = objWMIService.ExecQuery _
 ("SELECT * FROM Win32_OperatingSystem")
For Each objOS in colOSes
  If objOS.Version = "5.1.2600" Then
    If objOS.ServicePackMajorVersion = "2" Then
      g_strSP2 = g_strSP2 & strComp & vbCrLf
      g_intSP2 = g_intSP2 + 1
    ElseIf objOS.ServicePackMajorVersion = "1" Then
      g_strSP1 = g_strSP1 & strComp & vbCrLf
      g_intSP1 = g_intSP1 + 1
    Else
      g_strSP0 = g_strSP0 & strComp & vbCrLf
      g_intSP0 = g_intSP0 + 1
    End If
    GetSP = 0
  Else
    g_intNotXP = g_intNotXP + 1
  End If
Next
GetSP = 0

End Function

'******************************************************************************

'Write or append data to text file.
Sub WriteTextFile(strFileName)

On Error Resume Next

'Open text file for output.
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strFileName) Then
  Set objTextStream = objFSO.OpenTextFile(strFileName, FOR_APPENDING)
Else
  Set objTextStream = objFSO.CreateTextFile(strFileName)
End If

'Write data to file.
objTextStream.WriteLine "Inventory of Windows XP Service Packs"
objTextStream.WriteLine "Taken " & Now
objTextStream.WriteLine vbCrLf & "Computers Running Windows XP"
objTextStream.WriteLine "============================"
objTextStream.WriteLine  "Total number: " & (g_intSP2 + g_intSP1 + g_intSP0)

objTextStream.WriteLine  vbCrLf & "Service Pack 2"
objTextStream.WriteLine  "--------------"
objTextStream.WriteLine  g_strSP2
objTextStream.WriteLine  "Total number: " & g_intSP2

objTextStream.WriteLine  vbCrLf & "Service Pack 1"
objTextStream.WriteLine  "--------------"
objTextStream.WriteLine  g_strSP1
objTextStream.WriteLine  "Total number: " & g_intSP1

objTextStream.WriteLine  vbCrLf & "No Service Pack"
objTextStream.WriteLine  "---------------"
objTextStream.WriteLine  g_strSP0
objTextStream.WriteLine  "Total number: " & g_intSP0

objTextStream.WriteLine  vbCrLf & "Computers Not Running Windows XP"
objTextStream.WriteLine  "================================"
objTextStream.WriteLine  "Total number: " & g_intNotXP

objTextStream.WriteLine  vbCrLf & "Could Not Connect To Computer"
objTextStream.WriteLine  "============================="
objTextStream.WriteLine  "Total number: " & g_intErr
objTextStream.WriteLine

objTextStream.Close

End Sub

Voici un exemple du contenu du fichier texte de sortie xpsp.txt :

Inventory of Windows XP Service Packs
Taken 3/15/2005 1:40:10 PM

Computers Running Windows XP
============================
Total number: 3

Service Pack 2
--------------
client1
client2
Total number: 2

Service Pack 1
--------------
client3
Total number: 1

No Service Pack
---------------
client4
Total number: 1

Computers Not Running Windows XP
================================
Total number: 0

Could Not Connect To Computer
=============================
Total number: 0

Nous avons décidé de ne pas extraire les noms des ordinateurs qui n'exécutent pas Windows XP, mais nous pourrions facilement les ajouter si nous voulions obtenir un inventaire plus complet. Et si nous voulons inclure toutes les mises à jour et non seulement les Service Packs, nous pouvons obtenir la liste des correctifs à l'aide de la classe WMI Win32_QuickFixEngineering. Dans la mesure où de nombreux correctifs peuvent être installés, nous pouvons alors afficher un inventaire par ordinateur, tel que nous l'avons fait dans les premiers exemples de code ci-dessus.

Nous pourrions par ailleurs ajouter du code qui déclenche l'installation du Service Pack 2 sur tous les ordinateurs où il n'a pas encore été installé. Pour ce faire, il suffit de concaténer les chaînes g_strSP1 et g_strSP0 (contenant les noms des ordinateurs Windows XP sans SP 2) pour obtenir une seule chaîne et d'utiliser Split(strSP1AndSP0, vbCrLf) pour la convertir à nouveau en tableau. Nous pouvons ensuite passer en revue ce tableau à l'aide de For Each et exécuter l'installation du Service Pack 2 sur chacun de ces ordinateurs. Cette approche pourrait nous permettre de déployer le Service Pack avec les paramètres de pare-feu par défaut autorisant l'administration à distance ou, sur un réseau équipé de son propre pare-feu, en désactivant ce dernier. Je pense que là, nous nous sommes surpassés.

Dans l'article suivant, nous vous expliquerons comment obtenir les mêmes informations sur le Service Pack auprès des ordinateurs joints à un domaine Active Directory.

Pour en savoir plus