23

I'm trying to create a simple list in a VBscript, but I'm unable to find something similar.

Basically, I'm working on Active directory, and I need to get all the groups a user is a member of for all the users within a domain. Now, every user might be a member of a different number of groups, so I plan to use a dictionary, with the key being the SAMID for the user, and the value being a list of all the groups he/she is a member of.

I can do this with a static array, but then I have to declare a random large size for the array which is not nice. What I would ideally like to do is have a python-like list, where I can simple do something like myList.Add and don't have to worry about sizing.

I tried using System.Collection.ArrayList, but I get an error when I run it:

PS C:\tmp> cscript.exe .\foo.vbs
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

C:\tmp\foo.vbs(1, 1) (null): 0x80131700

how can I accomplish this?

Malachi
  • 3,205
  • 4
  • 29
  • 46
NullPointer
  • 2,084
  • 7
  • 24
  • 38

4 Answers4

70

Get rid of the dictionary and unleash the power of an ArrayList.

Option Explicit

dim list
Set list = CreateObject("System.Collections.ArrayList")
list.Add "Banana"
list.Add "Apple"
list.Add "Pear"

list.Sort
list.Reverse

wscript.echo list.Count                 ' --> 3
wscript.echo list.Item(0)               ' --> Pear
wscript.echo list.IndexOf("Apple", 0)   ' --> 2
wscript.echo join(list.ToArray(), ", ") ' --> Pear, Banana, Apple

EDIT: I see you already tried the ArrayList, but got an error. It seems your installation of the dotnet framework is not correct (System.Collections.ArrayList is part of that). Microsoft has an article about how to solve that: http://answers.microsoft.com/en-us/windows/forum/windows_7-performance/error-code-0x80131700/3add8d80-00e0-4355-a994-8630d01c18f5

AutomatedChaos
  • 7,267
  • 2
  • 27
  • 47
  • Thanks, my first instinct was to use ArrayList, but I have solved the problem for now using Dictionary. I'll look at the MS link, cheers :) – NullPointer Nov 28 '12 at 10:25
  • I'm trying to access the list items with `.Item(0)` but I'm getting an error `Missing Default Property`. I've confirmed that there are at least 2 objects in the arraylist by using `.Count`. They are also objects, and not native types, if that matters. – crush Mar 18 '13 at 18:36
  • You cannot `echo` an object that hasn't a default property or a default property that does not return a primitive. If you know what kind of object it is you can display its appropriate property like `Name` or get information if it has a `ToString()` method. Alternatively, you can get its name with `wscript.echo typename(list.Item(i))`. – AutomatedChaos Mar 19 '13 at 07:00
  • Thanks for this - I never thought of using a .Net object in ASP/VBScript. Never felt right using a Dictionary. – James Culshaw Mar 21 '13 at 10:01
  • To add onto it there are other method for list -- list.Remove("Banana") but list.Exists("Pear") does not work as in Dictionary so for checking existence of an item use list.IndexOf("Apple", 0) where 0 is for index from where we want to search for existence of an item. – Ajay Gupta Mar 11 '15 at 11:32
  • 2
    This does require .NET to be installed, and while this is the case for most Windows computers, there are instances where it may not be. Just something to be aware of depending on your use case. – The Fluffy Robot Jul 19 '19 at 14:24
  • 2
    this gives your script a dependency on .NET 3.5 – Dave Cousineau Jun 25 '20 at 16:55
  • 1
    With new Windows versions, the NetFx3 optional feature is `DisabledWithPayloadRemoved` by default, making the dependency on .NET 3.5 an annoyance. And simply installing with `DISM /enable-feature /featurename:NetFx3` may fail unless the feature is fetched from a source. – weshouman Aug 11 '22 at 00:33
  • `Set list = CreateObject("System.Collections.ArrayList")` raises Runtime error 80131700. – Apostolos May 23 '23 at 07:02
12
Set dic = CreateObject("Scripting.Dictionary")

dic.Add "Item1", ""
dic.Add "Item2", ""
dic.Add "Item3", ""
ChiYoung
  • 836
  • 1
  • 7
  • 12
7

Here is an alternative as well... An actual List class that I created some time ago. You can freely use/modify it to suit your needs. The original class I built actually depends on another custom class called ArrayIterator.

Here is how to use it...

Set myList = New List
myList.Add("a")
myList.Add("b")
myList.Add("c")

' Iterate through the List using ArrayIterator. You can of course use other methods...
Set myListItr = myList.GetIterator
While myListItr.HasNext
  MsgBox myListItr.GetNext
Wend

' Iterate through the List by getting the underlying Array.
Dim element
For Each element In myList.GetArray
  MsgBox element
Next

Source code for List class:

Class List
  Private mArray

  Private Sub Class_Initialize()
    mArray = Empty
  End Sub

  ' Appends the specified element to the end of this list.
  Public Sub Add(element)
    If IsEmpty(mArray) Then
      ReDim mArray(0)
      mArray(0) = element
    Else
      If mArray(UBound(mArray)) <> Empty Then
        ReDim Preserve mArray(UBound(mArray)+1)        
      End If
      mArray(UBound(mArray)) = element
    End If
  End Sub

  '  Removes the element at the specified position in this list.
  Public Sub Remove(index)
    ReDim newArray(0)
    For Each atom In mArray
      If atom <> mArray(index) Then
        If newArray(UBound(newArray)) <> Empty Then
          ReDim Preserve newArray(UBound(newArray)+1)
        End If
        newArray(UBound(newArray)) = atom
      End If
    Next
    mArray = newArray
  End Sub

  ' Returns the number of elements in this list.
  Public Function Size
    Size = UBound(mArray)+1
  End Function

  ' Returns the element at the specified position in this list.
  Public Function GetItem(index)
    GetItem = mArray(index)
  End Function

  ' Removes all of the elements from this list.
  Public Sub Clear
    mArray = Empty
  End Sub

  ' Returns true if this list contains elements.
  Public Function HasElements
    HasElements = Not IsEmpty(mArray)
  End Function

  Public Function GetIterator
    Set iterator = New ArrayIterator
    iterator.SetArray = mArray
    GetIterator = iterator
  End Function

  Public Function GetArray
    GetArray = mArray
  End Function

End Class

Source code for ArrayIterator class:

Class ArrayIterator
  Private mArray
  Private mCursor  

  Private Sub Class_Initialize()
    mCursor = 0
  End Sub

  Public Property Let SetArray(array)
    mArray = array    
  End Property

  Public Function HasNext
    HasNext = (mCursor < UBound(mArray)+1)
  End Function

  Public Function GetNext
    GetNext = mArray(mCursor)
    mCursor = mCursor + 1
  End Function
End Class
Alex Fu
  • 5,509
  • 3
  • 31
  • 40
  • Thanks Alex, looks like an array which is dynamically resized everytime an item is added, pretty good workaround for a list – NullPointer Nov 28 '12 at 16:37
  • 1
    The behavior of your Remove function is atypical. It searches for the index provided as a parameter. Then it removes all occurrences of the value found at that position. I.e. assume this data (a, B, c, d, e, B, f). Remove(1) would return (a, c, d, e, f). As an added bonus the method contains an error: Size returns 7, not 5. – mgr326639 Dec 01 '12 at 16:28
0

What about the following?

weekdays = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday"
weekdays_list = Split(weekdays,",")
Apostolos
  • 3,115
  • 25
  • 28