Dictionary from VBS into Powershell

This topic contains 12 replies, has 2 voices, and was last updated by  David O’Brien 3 years, 7 months ago.

  • Author
    Posts
  • #12156

    David O’Brien
    Participant

    Hi all,

    I'm struggling a bit with this as I'm really not too fluent with VBS.

    Can anybody help me with the creation of this 3 dimensional dictionary in Powershell?

           For Each Key In List
                strDict(X,0) = CStr(Key)
                strDict(X,1) = CStr(List(Key))
                strDict(X,2) = right(CStr(Key),Length)
    

    Key is part of the array "List" build up of the properties "Name" and "Value".
    Length is just an integer, e.g. 2

    I just can't seem to find a way to get all three dimensions into a hashtable / array (?).

    Is this already enough info for you or do you need more info about the variable's contents?

    Thanks everybody and happy christmas!
    David

  • #12157

    Don Jones
    Keymaster

    I don't know that I'd call that a 3-dimensional dictionary, necessarily, but maybe I'm not grasping what you're after.

    What you've got is a dictionary wherein the values are objects having two properties.

    Assuming $d is your dictionary (also called a hash table), here's one way to do it:

    $x = New-Object -Type PSObject -Prop @{'Name'='xxx';'Value'=555}
    $d.Add('Key',$x)
    

    That's a dictionary having strings as keys (normal), with values that are a custom object having properties Name and Value. I'm not certain that's what you're after, though, so you'll have to let me know if not.

  • #12158

    David O’Brien
    Participant

    Hi Don,

    I'll test it right away. Will let you know if that was it.

    Thanks already!

  • #12160

    Don Jones
    Keymaster

    So.. OK, given that list, what's the desired output?

    You're going through each key in list... but what's the key? The name? That screen shot is just a straight dictionary already, using "Name" as the key and "Value" as the value. So I guess I don't understand what the end goal is? How are you wanting to use this information, or what is it you're wanting it to look like?

    I get how you want element A to be the name. I get how you want element B to be the value. I don't see where you're populating Length; you want Element C to be... 01, 04, 02?

  • #12162

    David O’Brien
    Participant

    I might then be not too far away from my end goal 😉

    I would now like to sort this dictionary and correct any missing elements.

    I want BaseVar01 to stay BaseVar01, BaseVar02 stays BaseVar02, BaseVar04 needs to become BaseVar03, and so on and this needs to happen with any element that could be part of this dictionary in the future. I can have no idea right now how large this dictionary will be in every given scenario (well, maximum up to BaseVar99)
    I am not allowed to change any order, so BaseVar04 always needs to be in that exact position (after BaseVar02 and before any other following BaseVarxx, BaseVarxx would be, after correction, BaseVar05)

    Not too easy to explain, I hope I'm making myself clear now.

  • #12163

    David O’Brien
    Participant

    Slow typing at 1am, sorry 😉

    Great explanation, thanks. I just tried to explain myself a bit more and what I am trying to achieve with my data.

    Thank you very much Don!

  • #12165

    David O’Brien
    Participant

    That does make a lot of sense to me now, thanks, and it looks BY FAR easier than the VBS stuff...
    Only, it doesn't work for me.

    If I use my list, then nothing happens at all. I put my list into $objects and nothing gets added to $fixed, just stays empty. My list variable says it's a hashtable, so it's already objects if I'm not mistaken, right? But shouldn't I be able to then say $list[1] to get the second element? Doesn't work with my list.

    If, for the sake of testing, I fill $objects manually (like you did) though, then $objects only contains "Value", no "Name" and I can't sort on it.

    I'm using Powershell 4 on Windows Server 2012 R2 by the way.

  • #12167

    David O’Brien
    Participant

    Got it 😉

    Had to rewrite a bit, but will blog it after x-mas!

    Thanks Don for helping here, much appreciated!

    David

  • #12189

    Don Jones
    Keymaster

    No problem – if you don't mind coming back and posting a URL to your blog, it'll help anyone who runs across this in the future.

    And a hashtable isn't quite like an object, but it's similar. I mean, it's a kind of object, certainly; it has properties named Key and Value. You should be able to pipe $list to Get-Member to see. But you usually access a hash table by key, like $list['BaseVar01'] rather than by index. That's the point of a hash table (dictionary), really.

    Anyway, glad you got it working, and happy holidays.

  • #12316

    David O’Brien
    Participant

    Hi all,

    this is my article where I needed that bit of script: http://www.david-obrien.net/2014/01/03/configmgr-application-base-variables-easy-way-powershell/

    Thanks for your help Don!

    Regards
    David

  • #12159

    David O’Brien
    Participant

    ok, going a bit more into detail:

    
            X = 0
            For Each Key In List
    		
                strDict(X,0) = CStr(Key)
                strDict(X,1) = CStr(List(Key))
                strDict(X,2) = right(CStr(Key),Length)
                X = X + 1
            Next
    

    List is something like this:
    List

    Is this still doable with your code?
    I would like to walk through my list and add the values with each new X value to a new element of my array.

  • #12161

    Don Jones
    Keymaster

    It'll help to let me know how you need to USE this construct you're creating. What you've produced in strDict is not a dictionary; it's an array. A two-dimensional array, wherein the first dimension has "X" elements and the second dimension has 3 elements. Like an X-by-3 spreadsheet. A dictionary's super power is that it lets you specify a key and then get the associated value. PowerShell does dictionaries awesome. It does arrays, too, but they're different, and you use them differently.

    That's why it'd help to know how you plan to use this thing you're making. A one-for-one translation from VBScript isn't necessarily leveraging PowerShell. You can end up working a lot harder to recreate some VBS effect, when in fact PowerShell could get you to the end result a lot more easily than VBS did.

    PowerShell, for example, tends to do really well with collections (arrays) of objects. VBS didn't, and you ended up mucking around with arrays a whole bunch. For example, if my goal was to have:

    Name     Value    Length
    -----    ------   -------
    Base01   Adobe    01
    

    That would simply be an object having three properties. Difficult in VBS, easy as cake in PowerShell. You could easily retrieve just one of them:

    $objects | Where Name -eq 'Base01'
    

    Extracting just the specified one from the collection. Collections are also easier to enumerate. You don't have to keep track of the upper boundary (like you're doing with X in your snippet); you just add a new object to the collection and PowerShell figures it out.

    So... knowing how this is supposed to be used in PowerShell might help me point you in a better direction...

  • #12164

    Don Jones
    Keymaster

    Yeah, I'd probably do this with objects.

    $objects = @()
    
    # do something to enumerate your existing list, I don't know what it's in
    # but for each list item...
    $objects += New-object -type psobject -prop @{Name='BaseVar01';Value='Adobe'} 
    

    So that gets you a collection of objects having everything you want. Now look, if your list is ALREADY OBJECTS, then you don't need to do anything. Just stick the list in $objects and continue. I don't need to pull off the last two digits separately.

    [int]$x = 1
    $fixed = $objects | sort name | foreach { 
      $_.name = "BaseVar{0:00}" -f $x
      $x++
    }
    $fixed
    

    Something like that. Not terribly efficient; going more for illustrative, but it should work. Untested though. You see, I'm not really checking to see if they're in order. I'm putting them into whatever order they're currently in, and then just going through them all and applying a new name. That {0:00} format string should get you two-digit numbers.

    The theory here is that it doesn't matter if 03 is missing. After sorting them, the third object is 03, regardless of what it used to be. So if 04 was in the third spot, it'll now be 03. And so on. You couldn't do this at all in VBS, not without a crapload of work that PowerShell's willing to do for you.

You must be logged in to reply to this topic.