Dictionary from VBS into Powershell

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

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.

Hi Don,

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

Thanks already!

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:

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.

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?

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…

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

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.

Slow typing at 1am, sorry :wink:

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!

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.

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.

Got it :wink:

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

Thanks Don for helping here, much appreciated!

David

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.

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