0

I've got to do an assignment for my internship and I cant figure out why the conditional wont work. I'm trying to get all the windowsservices except a few with a VBscript and write it to a textfile. Though I have no programming experiance and I'm at a loss here. Could you guys figure out what is wrong with this piece of code:

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
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328

3 Answers3

2

To cope with such problems in a more structured way:

(1) Start with the most simple script (list all 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

output:

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) Redirect the output in a temporary file (for further reference; see Step (5) below)

(3) Tackle the selection/skip problem in the 'natural' way (If ... Else ... 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

If you put

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

into the insertion point, you get an 'Object doesn't support this property or method' runtime error. Using .DisplayName as in

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

'works':

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

Then try:

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

to provoke a syntax error, and

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

output:

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

to make it 'work'.

(4) Having solved the problem in principle, you can think about the drawbacks of the solution and possible enhancements/improvements. Editing in a long _ connected sequence of Or clauses is cumbersome; a standard way out/around is using a dictionary:

  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

Now an easy to maintain data structure

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

replaces a more complex control structure.

(5) You can even use the dump of the full list (Step 2) and some editor macro to create a full sequence of dicSkip(..) = Empty lines and en/disable the current selection by commenting in/out. This would avoid surprises caused by typos too.

Update:

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
...
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
  • 1
    It might be a good idea to make the keys in the dictionary case-insensitive: `dicSkip.CompareMode = vbTextCompare` – Ansgar Wiechers Feb 24 '13 at 17:30
  • thanks for the detailed explanation. The only problem with this method is that it will not put the output generated bij this script into a .txt file which I needed to do. – user2104534 Feb 25 '13 at 10:28
  • @user2104534 - are you pulling my leg? (a) Writing to a file is implemented in the code you posted. (b) Step (2) shows to get file output for free. – Ekkehard.Horner Feb 25 '13 at 11:37
  • You're absolutely right and I appreciate all the effort you put into this! It's just that because of my poor knowledge of scripting keep failing to setup a working script my self and I'm starting to get a little desperate. – user2104534 Feb 25 '13 at 14:16
  • Thanks for all the help! Much appreciated! I am currently picking up scripting since this assignment. I am starting to like it, but I have a lot to learn though! – user2104534 Feb 28 '13 at 10:50
2

Well, you have here 2 good and very detailed answers that explains what you missed. Using Dictionary as @Ekkehard.Horner suggest should be most optimized way in this case as you have large list of values to compare with. But give a try on Select Case as well, just as alternative for other similar tasks. In Select Case you may use comma-delimited list of values, for example:

'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
Panayot Karabakalov
  • 3,109
  • 3
  • 19
  • 28
1

Firstly, a string by itself is not a condition. Instead of repeating strings, repeat the condition. The condition consists of an = operator with variables on either side. An example condition is answer = 42.

Secondly, you're comparing an object to a string. As Ekkehard Horner comments, you should probably compare the DisplayName property of the objService object.

Thirdly, in VBScript, a statement (like if) that spans multiple lines requires an underscore (_) at the end of all but the last line.

So change:

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

To:

If objService.DisplayName = "Human Interface Device Access" OR _
    objService.DisplayName = "Health Key and Certificate Management" OR _
Andomar
  • 232,371
  • 49
  • 380
  • 404