How To Practice PowerShell

January 10, 2011

in .Net,Dynamic Languages,Microsoft,PowerShell,Ruby

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 }

Tweets that mention How To Practice PowerShell -- Topsy.com
01.10.11 at 8:42 pm

{ 8 comments… read them below or add one }

Thomas 01.13.11 at 12:10 pm

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. ;-)

Doug Finke 01.13.11 at 3:10 pm

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.

$firstName = "John"
$lastName  = "Doe"            

"Hello, {0} {1}" -f $firstName, $lastName
Thomas 01.13.11 at 4:41 pm

Thanks!

I was still confused until I realized it was actually the “-f” that I had never used.

Doug Finke 01.13.11 at 7:05 pm

Thomas, thanks for pointing that out.

Anthony 01.16.11 at 5:29 pm

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

Doug Finke 01.16.11 at 8:36 pm

Thanks @Anthony. I will take a look.

James Craig Burley 01.19.11 at 5:43 pm

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!). :)

Doug Finke 01.19.11 at 6:40 pm

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 ;-)

Leave a Comment

You can use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Contrat Creative Commons

© 2007-2012, Doug Finke