Peek at PowerShell
Take a peek at some PowerShell code:
PS C:\> $properties = 'object oriented', 'duck typed', 'productive', 'fun'
PS C:\> foreach($property in $properties) { "PowerShell is $property" }
PowerShell is object oriented
PowerShell is duck typed
PowerShell is productive
PowerShell is fun
I am reading
“Seven Languages in Seven Weeks” by Bruce Tate and it is a great book. Looking through the Ruby chapter, I was struck by how well Mr. Tate communicates key concepts of the language and saw how the examples could be demonstrated in PowerShell.
I do a talk on PowerShell for .NET Developers (code camps and user groups), you can see the video I did for Microsoft’s Channel9 Geek Speak. I cover some these examples and more.
Let me know what else you’d like to see.
Launch a PowerShell Console and type along
Type along or copy and paste the examples to see how they work. At the end is a short Self-Study section. I added a sections for piping objects in PowerShell and accessing with the .NET framework.
Lightning Tour with the Console
Launch PowerShell. Type a command and get a response: Give these a try:
PS C:\> 'hello world'
hello world
PS C:\> $language = "PowerShell"
PS C:\> "hello, $language"
hello, PowerShell
PS C:\> $language = "my PowerShell"
PS C:\> "hello, ${language}"
hello, my PowerShell
PS C:\> $language = "your PowerShell"
PS C:\> "hello, $($language)"
hello, your PowerShell
PowerShell is object oriented
PS C:\> 4 4 PS C:\> (4).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Int32 System.ValueType PS C:\> 4 + 4 8 PS C:\> (4) | Get-Member -MemberType Method TypeName: System.Int32 Name MemberType Definition ---- ---------- ---------- CompareTo Method int CompareTo(System.Object value), int CompareTo(int value) Equals Method bool Equals(System.Object obj), bool Equals(int obj) GetHashCode Method int GetHashCode() GetType Method type GetType() GetTypeCode Method System.TypeCode GetTypeCode() ToString Method string ToString(), string ToString(string format), string ToString(System...
Decisions
PowerShell is like most object-oriented and procedural languages in many ways. Check out these expressions:
PS C:\> $x = 4 PS C:\> $x 4 PS C:\> $x -lt 5 True PS C:\> $x -le 4 True PS C:\> $x -gt 4 False PS C:\> ($false).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Boolean System.ValueType PS C:\> ($true).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Boolean System.ValueType
Evaluate to True or False
PS C:\> if($x -eq 4) {'This appears to be true'}
This appears to be true
PS C:\> if(-not $true) {'This appears to be true'}
PS C:\> if(! $true) {'This appears to be true'}
PS C:\> if(-not $false) {'This appears to be true'}
This appears to be true
PS C:\> if(! $false) {'This appears to be true'}
This appears to be true
While and until
PS C:\> while($x -lt 10) {$x = $x + 1}
PS C:\> $x
10
PS C:\> do {$x = $x - 1} until ($x -eq 1)
PS C:\> $x
1
PS C:\> while($x -lt 10) {$x = $x + 1; $x}
2
3
4
5
6
7
8
9
10
Using other than true or false
PS C:\> if(1) {'This appears to be true'}
This appears to be true
PS C:\> if('random string') {'This appears to be true'}
This appears to be true
PS C:\> if(0) {'This appears to be true'}
PS C:\> if($true) {'This appears to be true'}
This appears to be true
PS C:\> if($false) {'This appears to be true'}
PS C:\> if($null) {'This appears to be true'}
Logical Operators
PS C:\> $true -and $false False PS C:\> $true -or $false True PS C:\> $true -and 'test' True PS C:\> $true -and 'not an error' True PS C:\> $false -and 'not an error' False
Duck Typing
PS C:\> 4 + 'four'
Cannot convert value "four" to type "System.Int32". Error: "Input string was not in a correct forma
t."
At line:1 char:4
+ 4 + <<<< 'four'
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
PS C:\> (4).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Int32 System.ValueType
PS C:\> (4.0).GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Double System.ValueType
PS C:\> 4 + 4.0
8
PS C:\> 4 + 4.1
8.1
Type checking at runtime – Not at compile time
PS C:\> Function Add-ThemUp { 4 + 'four' }
PS C:\> Add-ThemUp
Cannot convert value "four" to type "System.Int32". Error: "Input string was not in a correct forma
t."
At line:1 char:26
+ Function Add-ThemUp { 4 + <<<< 'four' }
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Duck typing in action an array with a string and a double
PS C:\> $i = 0
PS C:\> $a = '100', 100.1
PS C:\> while ($i -lt 2) { [int]$a[$i]; $i++}
100
100
Arrays
PS C:\> $animals = 'lions', 'tigers', 'bears' PS C:\> $animals lions tigers bears PS C:\> $animals[0] lions PS C:\> $animals[2] bears PS C:\> $animals[10] PS C:\> $animals[-1] bears PS C:\> $animals[-2] tigers PS C:\> $animals[0..1] lions tigers PS C:\> (0..1).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\> @(1).GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\> $a = New-Object PSObject[] 3 PS C:\> $a[0] = 'zero' PS C:\> $a[1] = 1 PS C:\> $a[2] = 'two', 'things' PS C:\> $a zero 1 two things PS C:\> $a | Select-Object -First 1 zero PS C:\> $a | Select -Last 1 two things PS C:\> $a | Select -Last 2 1 two things PS C:\> $a = ((1, 2, 3),(10, 20, 30), (40, 50, 60)) PS C:\> $a[0][0] 1 PS C:\> $a[1][2] 30
Hashes
PS C:\> $numbers = @{1 = 'one'; 2 = 'two'; three = 3}
PS C:\> $numbers
Name Value
---- -----
three 3
2 two
1 one
PS C:\> $numbers[1]
one
PS C:\> $numbers[2]
two
PS C:\> $numbers.three
3
PS C:\> $stuff = @{ array = (1,2,3); string = 'Hi, mom!'}
PS C:\> $stuff.string
Hi, mom!
One way to search Arrays
PS C:\> $a = 5, 3, 4, 1 PS C:\> $a -gt 6 PS C:\> $a -gt 4 5 PS C:\> $a -ge 4 5 4
Piping
PS C:\> $a | sort
1
3
4
5
PS C:\> $a | ForEach {$_ * 2}
10
6
8
2
PS C:\> $a | % {$sum=0} {$sum+=$_} {$sum}
13
PS C:\> $a | % {$product=1} {$product*=$_} {$product}
60
PS C:\> $a | % {$sum=0} {'sum: {0} $_: {1} sum + $_: {2}' -f $sum, $_, ($sum+=$_)} {$sum}
sum: 0 $_: 5 sum + $_: 5
sum: 5 $_: 3 sum + $_: 8
sum: 8 $_: 4 sum + $_: 12
sum: 12 $_: 1 sum + $_: 13
13
PS C:\> $a | Where {$_ % 2 -eq 0} # even
4
PS C:\> $a | ? {$_ % 2 -eq 1} # odd
5
3
1
PS C:\> dir $PSHOME | Where {$_.length -gt 150kb}
Directory: C:\Windows\System32\WindowsPowerShell\v1.0
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 6/10/2009 5:24 PM 257847 Help.format.ps1xml
-a--- 7/13/2009 9:14 PM 452608 powershell.exe
-a--- 7/13/2009 9:23 PM 204800 powershell_ise.exe
-a--- 7/13/2009 9:23 PM 154624 pspluginwkr.dll
-a--- 6/10/2009 5:24 PM 168372 types.ps1xml
Quoting Rules
PS C:\> $i = 5 PS C:\> "The value of $i is $i." The value of 5 is 5. PS C:\> 'The value of $i is $i.' The value of $i is $i. PS C:\> 'As they say, "live and learn."' As they say, "live and learn." PS C:\> "As they say, 'live and learn.'" As they say, 'live and learn.' PS C:\> "As they say, ""live and learn.""" As they say, "live and learn." PS C:\> 'don''t' don't
Using the .NET Framework
PS C:\> [Math]::Pow(2,14)
16384
PS C:\> [Reflection.Assembly]::LoadWithPartialName("System.Winforms")
PS C:\> [Reflection.Assembly]::GetCallingAssembly()
GAC Version Location
--- ------- --------
True v2.0.50727 C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf385...
PS C:\> [IO.Path]::GetTempFileName()
C:\Users\finked\AppData\Local\Temp\tmpD522.tmp
PS C:\> ([IO.File]::ReadAllText("$PSHOME\Help.format.ps1xml")).Length
257844
Variable Substitution
PS C:\> ps win* | % { "Process Name: {0}" -f $_.Name}
Process Name: WindowsLiveWriter
Process Name: wininit
Process Name: winlogon
PS C:\> ps win* | % { "Process Name: $($_.Name)" }
Process Name: WindowsLiveWriter
Process Name: wininit
Process Name: winlogon
PS C:\> function ql {$args}
PS C:\> ql Tom Dick Harry John Jane | ForEach {"Hello ${_}"}
Hello Tom
Hello Dick
Hello Harry
Hello John
Hello Jane
Self-Study
Find:
- Information about PowerShell Cmdlets and the .NET Framework
- Information about PowerShell/.NET regular expressions
- Information about PowerShell ranges
Do:
- Print the string “Hello, world.”
- For the string “Hello, PowerShell.” find the index of the word “PowerShell”
- Print the string “This is sentence number 1.” where the number 1 changes from 1 to 10.
- Run a PowerShell program from a file.
- Bonus problem: Write a program that picks a random number. Let a player guess the number, telling the player whether the guess is too high or too low.
(Hint) Use the cmdlet Get-Command to discover the cmdlets that PowerShell provides.



{ 1 trackback }
{ 8 comments… read them below or add one }
Hey, great stuff! Education by simple example works well for me.
One thing that’s not clear is in the Variable Substitution section. What does the {0} do in the first line?
Now ..if I only knew where the best mallard hunting was.
Thanks for posting the question Thomas. For duck hunting, I can forward you several links I got spammed in my comments.
The {0} is the index of the item being printed in the format string. In this example {0} is $firstName and {1} is $lastName.
Thanks!
I was still confused until I realized it was actually the “-f” that I had never used.
Thomas, thanks for pointing that out.
Nice post! Thanks for sharing that.. It would be really cool if you could do a powershell quick reference such as the PQR http://rgruet.free.fr/PQR26/PQR2.6.html
Thanks @Anthony. I will take a look.
Hi Doug! Interesting summary of PowerShell features, but I think you misunderstand “duck typing”, as the first example you provide illustrates strong, versus weak, typing. The example that follows show that PowerShell does dynamic (“runtime”) versus static (“compile-time”) typing. The third example possibly shows a form of actual duck typing, but some non-duck-typed languages handle casts as shown (to [int]) — your example doesn’t show an explicit method invocation — so I don’t think it’s entirely convincing as indicative of PowerShell doing duck typing.
So it might be better to rework that example to use an explicit method invocation, and not the canonical “tostring” provided by .NET — create a “to_s” method as used in the book, added it to both the integer and string classes used by the array, and that example should (IIRC) demonstrate that PowerShell happily types ducks.
“True” duck typing generally implies one does not test for whether an object “isa” class, but rather forges ahead and invokes (testing via presence or absence of exceptions, perhaps ahead of time) the desired methods.
Hope this helps…if it does, I’ll happily send you a bill (quack!).
Thanks for the comment James. I did lift these examples from the Ruby section in “Seven Languages in Seven Weeks”. I believe I have an explicit example of duck typing and will post it when I find it.
Thanks again and I’d be happy to put that on your bill