2013-02-24 2 views
0

Je dois faire une affectation pour mon stage et je n'arrive pas à comprendre pourquoi le conditionnel ne fonctionnera pas. J'essaye d'obtenir tous les windowsservices sauf quelques uns avec un VBScript et l'écris dans un fichier texte. Bien que je n'ai aucune expérience de programmation et je suis à la perte ici. Pourriez-vous les gars comprendre ce qui ne va pas avec ce morceau de code:VBscript conditionnel pour chaque

Const ForAppending = 8 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objTextFile = objFSO.OpenTextFile _ 
("D:\Beheer\Scripts\Services\Services_For_this_server.txt", ForAppending, True) 
Set colServices = GetObject("winmgmts:").ExecQuery _ 
("Select * from Win32_Service") 
For Each objService in colServices 
If objService = "Human Interface Device Access" OR 
    "Health Key and Certificate Management" OR 
    "IKE and AuthIP IPsec Keying Modules" OR 
    "PnP-X IP Bus Enumerator" OR 
    "IP Helper" OR 
    "CNG Key Isolation" OR 
    "KtmRm for Distributed Transaction Coordinator" OR 
    "Server" OR 
    "Workstation" OR 
    "Link-Layer Topology Discovery Mapper" OR 
    "TCP/IP NetBIOS Helper" OR 
    "Multimedia Class Scheduler" OR 
    "Windows Firewall" OR 
    "Distributed Transaction Coordinator" OR 
    "Microsoft iSCSI Initiator Service" OR 
    "Windows Installer" OR 
    "Network Access Protection Agent" OR 
    "Netlogon" OR 
    "Network Connections" OR 
    "Network List Service" OR 
    "Network Location Awareness" OR 
    "Network Store Interface Service" OR 
    "Performance Counter DLL Host" OR 
    "Performance Logs & Alerts" OR 
    "Plug and Play" OR 
    "IPsec Policy Agent" OR 
    "Power" OR 
    "User Profile Service" OR 
    "Protected Storage" OR 
    "Remote Access Auto Connection Manager" OR 
    "Remote Access Connection Manager" OR 
    "Routing and Remote Access" OR 
    "Remote Registry" OR 
    "RPC Endpoint Mapper" OR 
    "Remote Procedure Call (RPC) Locator" OR 
    "Remote Procedure Call (RPC)" OR 
    "Resultant Set of Policy Provider" OR 
    "Special Administration Console Helper" OR 
    "Security Accounts Manager" OR 
    "Smart Card" OR 
    "Task Scheduler" OR 
    "Smart Card Removal Policy" OR 
    "Secondary Logon" OR 
    "System Event Notification Service" OR 
    "Remote Desktop Configuration" OR 
    "Internet Connection Sharing (ICS)" OR 
    "Shell Hardware Detection" OR 
    "SNMP Trap" OR 
    "Print Spooler" OR 
    "Software Protection" OR 
    "SPP Notification Service" OR 
    "SSDP Discovery" OR 
    "Secure Socket Tunneling Protocol Service" OR 
    "Microsoft Software Shadow Copy Provider" OR 
    "Telephony" 
THEN "" 
ELSE 
objTextFile.WriteLine(objService.DisplayName) 
Next 
objTextFile.Close 
+0

Que voulez-vous arriver, et de quelle manière il ne « fonctionne pas »? –

Répondre

1

Tout d'abord, une chaîne par lui-même est pas une condition. Au lieu de répéter les chaînes, répétez la condition . La condition consiste en un opérateur = avec des variables de chaque côté. Un exemple de condition est answer = 42.

Deuxièmement, vous comparez un objet à une chaîne. Comme Ekkehard Horner commente, vous devriez probablement comparer la propriété DisplayName de l'objet objService.

Troisièmement, dans VBScript, une instruction (telle que if) qui s'étend sur plusieurs lignes nécessite un trait de soulignement (_) à la fin de toutes sauf la dernière ligne.

donc changer:

If objService = "Human Interface Device Access" OR 
    "Health Key and Certificate Management" OR 

Pour:

If objService.DisplayName = "Human Interface Device Access" OR _ 
    objService.DisplayName = "Health Key and Certificate Management" OR _ 
+0

-0.49 vous ne pouvez pas comparer objServerice à une chaîne, objServerice.DisplayName doit être utilisé. –

+0

désolé d'être un parasite, mais maintenant le «_» (s'il vous plaît continuer le marqueur de ligne) est mising après les «OR». (+1, merci pour l'amélioration (s)). –

+0

@ Ekkehard.Horner: Vous avez raison. L'analyseur doit faire allusion à cela lorsque vous essayez de l'exécuter cependant. – Andomar

2

Pour faire face à ces problèmes d'une manière plus structurée:

(1) Commencez par le script le plus simple (liste tous services):

Dim colServices : Set colServices = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service") 
    Dim n   : n    = 0 
    Dim objService 
    For Each objService in colServices 
     WScript.Echo n, objService.DisplayName 
     n = n + 1 
    Next 

sortie:

0 Adobe Flash Player Update Service 
1 Alerter 
2 Application Layer Gateway Service 
3 Application Management 
4 ASP.NET State Service 
5 Windows Audio 
6 Background Intelligent Transfer Service 
... 

105 Automatic Updates 
106 Wireless Zero Configuration 
107 Network Provisioning Service 

(2) de redirection de la sortie dans un fichier temporaire (à titre de référence; voir l'étape (5) ci-dessous)

(3) Tackle la sélection/saut problème de la manière 'naturelle' (Si ... Sinon ... End If):

Dim colServices : Set colServices = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service") 
    Dim n   : n    = 0 
    Dim objService 
    For Each objService in colServices 
     Dim sSkipped : sSkipped = Space(7) 
     [insertion point] 
     WScript.Echo n, sSkipped, objService.DisplayName 
     n = n + 1 
    Next 

Si vous mettez

If objService = "Alerter" Then sSkipped = "skipped" 

dans le point d'insertion, vous obtenez une erreur d'exécution 'Objet ne prend pas en charge cette propriété ou cette méthode'. En utilisant .DisplayName comme dans

If objService.DisplayName = "Alerter" Then sSkipped = "skipped" 

'fonctionne':

0   Adobe Flash Player Update Service 
1 skipped Alerter 
2   Application Layer Gateway Service 
3   Application Management 

Ensuite, essayez:

If objService.DisplayName = "Alerter" Or 
    objService.DisplayName = "Application Management" Then sSkipped = "skipped" 

pour provoquer une erreur de syntaxe et

If objService.DisplayName = "Alerter" Or _ 
    objService.DisplayName = "Application Management" Then sSkipped = "skipped" 

sortie:

0   Adobe Flash Player Update Service 
1 skipped Alerter 
2   Application Layer Gateway Service 
3 skipped Application Management 
4   ASP.NET State Service 
... 

pour le 'travailler'.

(4) Après avoir résolu le problème en principe, vous pouvez penser aux inconvénients de la solution et aux améliorations/améliorations possibles. L'édition dans une séquence connectée depuis longtemps des clauses Or est lourde; une manière standard sur/autour utilise un dictionnaire:

Dim colServices : Set colServices = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service") 
    Dim dicSkip  : Set dicSkip  = CreateObject("Scripting.Dictionary") 
    dicSkip("Alerter"    ) = Empty 
    dicSkip("Application Management") = Empty 
    WScript.Echo "planning to skip:", Join(dicSkip.Keys(), ", ") 
    Dim n   : n    = 0 
    Dim objService 
    For Each objService in colServices 
     Dim sSkipped : sSkipped = Space(7) 
     If dicSkip.Exists(objService.DisplayName) Then sSkipped = "skipped" 
     WScript.Echo n, sSkipped, objService.DisplayName 
     n = n + 1 
    Next 

maintenant facile de maintenir la structure de données

dicSkip("Alerter"    ) = Empty 
    dicSkip("Application Management") = Empty 

remplace une structure de contrôle plus complexe. (5) Vous pouvez même utiliser la sauvegarde de la liste complète (étape 2) et une macro d'éditeur pour créer une séquence complète de lignes dicSkip(..) = Empty et activer/désactiver la sélection en cours en commentant in/out. Cela éviterait aussi les surprises dues aux fautes de frappe.

Mise à jour:

type servicedump.vbs 

Option Explicit 

Const sOutFSpec = ".\servicedump.txt" 

Dim goFS  : Set goFS  = CreateObject("Scripting.FileSystemObject") 
Dim oOutFile : Set oOutFile = goFS.CreateTextFile(sOutFSpec, True) 
Dim colServices : Set colServices = GetObject("winmgmts:").ExecQuery("Select * from Win32_Service") 
Dim dicSkip  : Set dicSkip  = CreateObject("Scripting.Dictionary") 
dicSkip("Alerter"    ) = Empty 
dicSkip("Application Management") = Empty 
Dim objService 
For Each objService in colServices 
    If Not dicSkip.Exists(objService.DisplayName) Then oOutFile.WriteLine objService.DisplayName 
Next 
oOutFile.Close 

cscript servicedump.vbs 

type servicedump.txt 
Adobe Flash Player Update Service 
Application Layer Gateway Service 
ASP.NET State Service 
Windows Audio 
... 
+1

Cela peut être une bonne idée de rendre les clés du dictionnaire insensibles à la casse: 'dicSkip.CompareMode = vbTextCompare' –

+0

merci pour l'explication détaillée. Le seul problème avec cette méthode est qu'elle ne mettra pas la sortie générée par ce script dans un fichier .txt que je devais faire. – user2104534

+0

@ user2104534 - Tirez-vous ma jambe? (a) L'écriture dans un fichier est implémentée dans le code que vous avez publié. (b) L'étape (2) montre que la sortie du fichier est gratuite. –

2

Eh bien, vous avez ici 2 bonnes et des réponses très détaillées qui explique ce que vous avez manqué. En utilisant Dictionary comme @ Ekkehard.Horner suggère devrait être la manière la plus optimisée dans ce cas, car vous avez une grande liste de valeurs à comparer avec. Mais essayez aussi Select Case, juste comme alternative pour d'autres tâches similaires. En Select Case vous pouvez utiliser la liste de valeurs, par exemple délimité par des virgules:

'instead of... 
For obj In Collection 
    If obj.property = "X" Or _ 
    obj.property = "Y" Or _ 
    obj.property = "Z" Then 
     '... 
    Else 
     '... 
Next 

'you can... 
For obj In Collection 
    Select Case obj.property 
     Case "X", "Y", "Z" 
      'skip (or whatever) 
     Case Else 
      'write (or whatever) 
    End Select 
Next 
+0

+1 - en regardant 'Select Case' quand' IF' pose des problèmes si cela en vaut vraiment la peine. –