Properly Declare a List Collection? - powershell

In Powershell V4, how would I properly declare a List<> collection?
I tried declaring it like this
$listCollection = New-Object 'System.Collections.Generic.List<string>'
It didn't work and gave me errors.

In Powershell, you need to use square brackets [...] when specifying the type of the list's items:
PS > $listCollection = New-Object System.Collections.Generic.List[string]
PS > $listCollection.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True List`1 System.Object
PS >
Note that this is different from C#, which would use angle brackets <...>.

Related

Cast based on variable

I am trying to cast based on the value of a variable, ultimately to be able to actually test to see if $castFrom is of the $castTo type. I can of course do it with a switch like this
$castTo = '[xml]'
$castFrom = #"
<Settings>
<MachineLogFileArchiveFolder></MachineLogFileArchiveFolder>
</Settings>
"#
switch ($castTo) {
'[int]' {
$castResult = [int]$castFrom
}
'[xml]' {
$castResult = [xml]$castFrom
}
}
But that's a little ugly. What I really want too do is something more like this
$castResult = [($castTo)]$castFrom
or this
$castResult = [$($castTo)]$castFrom
but I am getting the impression the switch really is my only option.
Maybe you could use the ToType method:
$castResult = $castFrom.ToType($castTo, [System.Globalization.DateTimeFormatInfo]::CurrentInfo)
Somehow this doesn't work for your example but could be a starting point.
However, you can do this using the Invoke-Expression cmdlet:
$castResult = Invoke-Expression -Command ('[{0}]$castFrom' -f $castTo)
The -as and -is operators just seem simpler for this situation.
$castto = 'string'
$castfrom = 234
$castfrom.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
$castresult = $castfrom -as $castto
$castresult.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
$castfrom -is $castto
False
$castresult -is $castto
True

Unable to set Comobject Value

I have a snippet of code that opens a word template, then attempts to set values of named FormFields.
$options = #{
'foo' ='bar';
'bizz' = 'buzz';
}
$document = 'C:\Form_template.doc'
$word = new-object -ComObject Word.application
$doc = $word.Documents.Open($document)
$word.visible = $true
$fields = $doc.FormFields
$fields.item('foo').Result = $options['foo']
$fields.item('bizz').Result = $options['bizz']
When running this snippet, the form fields are not set properly. However, when I run
$fields.item('foo').Result = 'bar'
$fields.item('bizz').Result = 'buzz'
The values are set as desired.
Edit: Here's an example in Interactive shell
PS C:\>$fields.item('foo').Result = $options['foo']
PS C:\>$fields.item('bizz').Result = $options['bizz']
PS C:\> $doc.FormFields.Item('foo').Result
PS C:\> $doc.FormFields.Item('bizz').Result
PS C:\>#Now let's try setting the values directly with a string.
PS C:\>$fields.item('foo').Result = 'bar'
PS C:\>$fields.item('bizz').Result = 'buzz'
PS C:\> $doc.FormFields.Item('foo').Result
bar
PS C:\> $doc.FormFields.Item('bizz').Result
buzz
Why am I not able to set the FormField values using values from the hash?
Per a suggestion from Ben casting the string with [string]$options['bizz'] resulted in setting the value correctly.
PS C:\>$fields.item('bizz').Result = [string]$options['bizz']
PS C:\> $doc.FormFields.Item('foo').Result
buzz
Upon further investigation I found that casting the hash value to string returned a different type vs using .toString()
PS C:\> $options['bizz'].getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
PS C:\> $options['bizz'].toString().getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
PS C:\> [string]$options['bizz'].getType()
string
I'm interested in why that is, but that would be a topic for another thread. Proper casting resolved my issue.

Powershell split by '_' return empty

So i have folder with several files:
$files = #(Get-ChildItem "myPath")
I can see via the debugger that $files contains several items and i want to take the first:
$files[0] = "123_this.is.string"
And i want to split in by '_' and take 123
$splitted = $files[0] -split "_"
So here i can see that $splitted is empty.
Any suggestions why this strange behavior ?
$files[0] isn't a string but a FileSystemInfo Object.
$files[0].getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True FileInfo System.IO.FileSystemInfo
So to get it work you have to use the split function to the filename of the file which is a string.
$files[0].name.getType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
With this it should work:
$files[0].name.split("_")
Try:
$files[0].ToString().split("_")

powershell first argument is of type object[]?

If i run the following code in PowerShell ISE
cls
Function XmlTransformaton ($sourceFile, $targetFile, $xsltFile)
{
echo "sourceFile: " + $sourceFile.GetType();
echo "targetFile: $targetFile";
echo "xsltFile: $xsltFile";
}
XmlTransformaton("C:\temp\TransfromTest\Test.rdl", "C:\temp\TransfromTest\Test.rdl", "C:\temp\TransfromTest\Test.xslt");
i get the following output
sourceFile:
+
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
targetFile:
xsltFile:
Why on earth is the first argument of type array? The result of this is that all other parameters are empty!
Because you're passing an array as your first (and only) argument. It looks like you want to be doing this instead:
XmlTransformaton "C:\temp\TransfromTest\Test.rdl" "C:\temp\TransfromTest\Test.rdl" "C:\temp\TransfromTest\Test.xslt"
Which gives:
sourceFile:
+
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String System.Object
targetFile: C:\temp\TransfromTest\Test.rdl
xsltFile: C:\temp\TransfromTest\Test.xslt
Multiple arguments are passed to functions as Some-Function $param1 $param2 $paramN, no need to use parenthesis and comma separated args - that's how you construct an array

Create an array, hashtable and dictionary?

What is the proper way to create an array, hashtable and dictionary?
$array = [System.Collections.ArrayList]#()
$array.GetType() returns ArrayList, OK.
$hashtable = [System.Collections.Hashtable]
$hashtable.GetType() returns RuntimeType, Not OK.
$dictionary = ?
How to create a dictionary using this .NET way?
What is the difference between dictionary and hashtable? I am not sure when I should use one of them.
The proper way (i.e. the PowerShell way) is:
Array:
> $a = #()
> $a.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
Hashtable / Dictionary:
> $h = #{}
> $h.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Hashtable System.Object
The above should suffice for most dictionary-like scenarios, but if you did explicitly want the type from Systems.Collections.Generic, you could initialise like:
> $d = New-Object 'system.collections.generic.dictionary[string,string]'
> $d.gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Dictionary`2 System.Object
> $d["foo"] = "bar"
> $d | Format-Table -auto
Key Value
--- -----
foo bar
If you want to initialize an array you can use the following code:
$array = #() # empty array
$array2 = #('one', 'two', 'three') # array with 3 values
If you want to initialize hashtable use the following code:
$hashtable = #{} # empty hashtable
$hashtable2 = #{One='one'; Two='two';Three='three'} # hashtable with 3 values
Hashtable and dictionary in Powershell is pretty much the same, so I suggest using hashtable in almost all cases (unless you need to do something in .NET where Dictionary is required)