powershell array, add, remove elements

Arrays are convenient to use but like in any language adding removing elements dynamically is not very efficient. It is more efficient to use System.Collections.ArrayList or generic List class (instantiating generics is another topic) than Arrays

PS >
PS > [array]$names = @()
PS > $names += "Q"
PS > $names += "picard"
PS > $names += "spock"
PS > $names += 10

PS > $names.Count
4

PS > $names[2]
spock

PS > $names[6]

PS > $names
Q
picard
spock
10
PS >
PS > $names.count = 2
"Length" is a ReadOnly property.
At line:1 char:8
+ $names. <<<< count = 2
 + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
 + FullyQualifiedErrorId : PropertyAssignmentExceptionPS >

PS > $names.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

PS > $names[4]
10
PS > $names[4].GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType

PS > $names[2]
spock
PS > $names[2].GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

When declaring an array of one, it might not be an Array

Consider an array of arrays, an array of two elements, each element is in turn an array

PS> $a = @( @("row1-a", "row1-b", "row1-c"), @("row2-a", "row2-b") )
PS> $a.count
2
PS>$a[0].count
3
PS>$a[1].count
2

Now an array of one – not what we would normally expect

PS> $a = @( @("row1-a", "row1-b", "row1-c") )
PS> $a.Count
3

$a becomes just array of three strings instead of an array of 1 element, to get this you have to start the array declaration with a comma

PS> $a = @(, @("row1-a", "row1-b", "row1-c") )
PS> $a.Count
1

Starting an array with more than one element with a comma is fine, it does not add an extra empty element at the beginning :)

References:
http://www.vistax64.com/powershell/13950-how-add-entries-array.html
http://www.powershellpro.com/powershell-tutorial-introduction/variables-arrays-hashes/
http://stackoverflow.com/questions/1390782/jagged-powershell-array-is-losing-a-dimension-when-only-one-element-exists
http://www.justaprogrammer.net/2011/03/30/an-array-of-one-item-in-powershell/

Advertisements

powershell from cmd, msbuild, return value

Returning a value from a powershell script

exit <returnvalue>

Use return value in other environments like cmd, msbuild

When running the script from other environments like cmd or msbuild we normally use

powershell.exe <scriptname.ps1>

this does not get the actual error value returned from the script, the return value from this command will be ‘0’ if there was no error or no return value and ‘1’ if the script exited with an error value. To get the actual error value returned from the script use

powershell.exe <scriptname.ps1>; exit $LastExitCode

References:

http://blog.brianhartsock.com/2009/10/20/using-powershell-scripts-from-msbuild-scheduled-tasks-etc/
http://powershell.com/cs/blogs/tips/archive/2009/05/18/returning-exit-code-from-script.aspx
http://weblogs.asp.net/soever/archive/2010/07/14/returning-an-exit-code-from-a-powershell-script.aspx

See Also

powershell variable, pipeline variable, $ everything

Variable

  • prefix name with ‘$’ symbol
  • $v = “hello” and use it as $v everywhere
  • not when you use Set-Variable
    • Set-Variable -Name v -Value “hello”
  • no need to specify type if required [int]$number = 1
  • Get-Variable lists all variables defined
  • Pipeline variable $_
    • implicit object in the pipeline
    • Get-Service | Where-Object {$_.DisplayName -like “*Microsoft*”}
    • Get-Service | %{$_.DisplayName}
  • $? – success status of last command
  • $Args – arguments of a function
  • Special characters in variable
    • The name will have to be enclosed in {}
    • for example if  variable name contains #, an object has EMP# as a member, use  $emp.{EMP#} to access the variable

powershell general usage

  • you need to provide path for the ps script for it to work; dot-source it even if in the current directory: .\test.ps1 (this is like in a linux shell)
  • NOT case-sensitive; nothing is including variable names defined by you
  • Variable
    • prefix name with ‘$’ symbol
    • $v = “hello” and use it as $v everywhere
    • not when you use Set-Variable
    • no need to specify type; if required [int]$number = 1
  • functions have to be defined before you can use them, literally the order in the ps file
  • End of line is end of command; multi-line use backtick ` to indicate the command continues on next line (no space after backtick)
  • Semi-colon ; can be used to separate multiple commands on the same line
  • Comment character #; multi-line comments <# ……. #>
  • [] brackets can be used to specify the object. [String] represents the string object
  • filtering – select-string, select-object (search web for “powershell filtering”)
  • formatting – format-list (shortcut fl), format-table (ft), format-wide (fw)

powershell members of an object, pipe, inputobject

use Get-Member

pipe the object to get-member  or use -InputObject

Get-Member -Force will get all members, check help for diff options

PS C:\>Get-Service | Get-Member
PS C:\>”hello” | Get-Member
PS C:\>1 | Get-Member
PS C:\>Get-Member -InputObject “hello”

Piping and -InputObject are different in that – when the input is via pipe, get-member gives information about all the different types of objects piped to it, where as for -InputObject it gives the type of the container itself

for example:

PS C:\>1 | Get-Member
PS C:\> Get-Member -InputObject 1

Will return information for TypeName: System.Int32

whereas

PS C:\>$a = Get-Service
PS C:\>$a | Get-Member
PS C:\>Get-Member -InputObject $a

will return information about the windows service controller object and the array object respectively since the second one treats $a as it is ‘an array of objects’