Powershell Notes
Powershell Notes
(OUSTERHOUT, J., Scripting: Higher-Level Programming for the 21st Century, IEEE Computer, Vol. 31, No. 3, March 1998, pp. 23-30.)
Practice
You need a Windows host running on a physical or virtual machine with working access to the internet, and
with PowerShell v2.0 installed.
Log in and open a terminal window, download the examples as we go along from
http :// www . ansatt . hig . no / erikh / t u t o r i a l - p o w e r s h e l l / FILENAME
(or download all at once with filename powershell-examples.zip but remember to unblock before unzip)
We assume that you are using PowerShell 2.0 (as shipped with Windows 7 and Windows Server
2008R2) and have installed the PowerShell Community Extensions from http://pscx.codeplex.
com/ and the GnuWin32 utilities http://sourceforge.net/projects/getgnuwin32/files/ (where
you will find wget etc).
To allow for execution of scripts in powershell you need to set the correct execution policy:
# check what is current policy
Get-ExecutionPolicy
# change to only require signature on remote scripts
Set-ExecutionPolicy RemoteSigned
# you probably need to "run as administrator" to do this
To install PowerShell Community Extensions
# download Pscx-2.x.x.x.zip using a webbrowser
# windows explorer and browse to where it is
# right click on Pscx-2.x.x.x.zip, choose properties
# click unblock, ok
# right click, extract all to $PSHOME\Modules dir
# $PSHOME is probably
# C:\Windows\System32\Windows\PowerShell\v1.0
Import-Module Pscx
# place this command in $profile so it is run every time
# you start PowerShell, or do it globally with
# "run as administrator" and
New-Item $pshome\profile.ps1 -type file
notepad $pshome\profile.ps1
To install GnuWin32
# Run setup program from
# http://sourceforge.net/projects/getgnuwin32/files/
# cd to the directory where it was downloaded
download.bat # answer yes to a couple of questions
# run powershell as administrator
VARIABLES
PowerShell commands are called cmdlets (pronounced commandlets) and have the syntax verb-noun,
e.g. Write-Host. Fortunately most of the cmdlets have aliases corresponding to the commands
you might know from DOS (cmd.exe) or Unix/Linux. In addition there is also a short PowerShell
alias to most cmdlets. To find the cmdlet to a command you know from before you can use the
cmdlet Get-Alias:
Get-Alias ls
# is there a cmdlet c o r r e s p o n d i n g to Unix / Linux ls ?
Get-Alias
# list all the aliases
# use the DOS command findstr to list all lines c o n t a i n i n g G e t - C h i l d I t e m
Get-Alias | findstr Get-ChildItem
# do the same thing but do it the P o w e r S h e l l - w a y :
Get-Alias | Where-Object { $_ . Definition - eq " Get-ChildItem " }
# dont worry about this unknown syntax for now , we will get to it soon
To get help with the cmdlets, use the cmdlet Get-Help, e.g. Get-Help Write-Host | more. A
nice feature is that you can view the help page in your browser (on the internet) by adding the
parameter -online, e.g. Get-Help Write-Host -online.
Note that you can use TAB-completion on both commands and parameters.
Variables
Single Variables
VARIABLES
# s i n g l e - v a r . ps1
$firstname = " Mysil "
$lastname = " Bergsprekken "
$fullname = " $firstname $lastname "
Write-Host " Hello $fullname , may I call you " `
" $firstname `? "
Exercise
$name = " Mysil "
VARIABLES
$name
$name "
$name '
Variables are expanded/interpolated inside double quotes, but not inside single quotes.
1.1
Arrays
Arrays
One-dimensional arrays:
# array . ps1
$os = @ ( " linux " , " windows " )
$os += @ ( " mac " )
Write-Host $os [1]
# print windows
Write-Host $os
# print array values
Write-Host $os . Count # length of array
Ivar Moe
array values
array keys
length of array
VARIABLES
Associative arrays are created with @{...} and are called Hashtables in PowerShell.
1.2
Structures/Classes
Structures/Classes
A simple object used as a struct:
# struct . ps1
$myhost = New-Object PSObject - Property `
@ { os = " " ;
sw = @ ();
user = @ {}
}
$myhost . os = " linux "
$myhost . sw += @ ( " gcc " ," flex " ," vim " )
$myhost . user += @ {
" frodeh " = " Frode Haug " ;
" monicas " = " Monica Strand "
}
Write-Host $myhost . os
Write-Host $myhost . sw [2]
Write-Host $myhost . user [ " monicas " ]
Of course, since PowerShell is based on the object-oriented framework .NET, creating and manipulating objects is a world by it self, there are a plethora of ways of doing these things.
See what kind of object this is by running the commands on the command line and doing
$myhost
$myhost.GetType()
$myhost | Get-Member
Note also that we dont need the line continuation character ` when inside a block ({...}).
1.3
Command-line args
Command-Line Arguments
All command-line arguments in the array $args
Scriptname retrieved from the object $MyInvocation
# c l i - a r g s . ps1
Write-Host " I am " $MyInvocation . Invocat ionName `
" and have " $args . Count " arguments " `
" first is " $args [0]
INPUT
$MyInvocation is one of PowerShells builtin variables. Again, check what kind of object this is
with
$MyInvocation.GetType()
$MyInvocation | Get-Member
# or check what a typical PowerShell command returns
Get-Process | Get-Member
(Get-Process).GetType()
# contrast this with a traditional cmd command
ipconfig | Get-Member
(ipconfig).GetType()
For all special variables in PowerShell, a good resource is http://www.neolisk.com/techblog/
powershell-specialcharactersandtokens
Exercise
Rewrite the previous script to only have one string (just one set of double quotes (")), one at
the beginning and one at the end, do not use single quotes either
2
2.1
Input
Input
can be executed as
Write-Output " hey hey ! " | .\ input-pipe . ps1
$input (another one of PowerShells builtin variables) is a special variable which enumerates the
incoming objects in the pipeline.
CONDITIONS
2.2
System commands
Using $(expr) inside a string will treat it as an ad-hoc variable evaluating the expression expr and
inserting the output into the string.
3
3.1
Conditions
if/else
if/else
# if . ps1
if ( $args . Length - ne 1) {
Write-Host " usage : " `
$MyInvocation . Invocat ionName `
" < argument > "
}
3.2
Operators
Comparison
CONDITIONS
10
Operator
lt
gt
le
ge
eq
ne
Meaning
Less than
Greater than
Less than or equal to
Greater than or equal to
Equal to
Not equal to
Note that many other test operators (e.g. file tests) are used as methods in the objects instead of
separate operators.
Boolean
Operator
not
!
and
or
Meaning
Not
Not
And
Or
# i f - n u m - s t r i n g . ps1
if ( $args . Count - ne 2) {
Write-Host " usage : " `
$MyInvocation . Invocat ionName `
" < argument > < argument > "
exit 0
} elseif ( $args [0] - gt $args [1]) {
Write-Host $args [0] " larger than " $args [1]
} else {
Write-Host $args [0] " smaller than or " `
" equal to " $args [1]
}
if ( Test-Path $args [0]) {
if (!( Get-Item $args [0]). PSIsContainer ) {
Write-Host $args [0] " is a file "
}
}
There are not separate comparison operators for numbers and strings. Be careful when comparing objects with different types. Behaviour might be a bit strange (see page 209 of Mastering
PowerShell by Weltner):
$ 123 -lt "123.4"
False
$ 123 -lt "123.5"
True
A set of file test operators is not available since this functionality is covered through cmdlets (e.g.
Test-Path) and methods (e.g. PSIsContainer).
CONDITIONS
11
Boolean example
# if-bool . ps1
if ((1 - eq 2) - and (1 - eq 1) - or (1 - eq 1)) {
Write-Host " And has precedence "
} else {
Write-Host " Or has precedence "
}
# force OR p r e c e d e n c e :
if ((1 - eq 2) - and ((1 - eq 1) - or (1 - eq 1))) {
Write-Host " And has precedence "
} else {
Write-Host " Or has precedence "
}
AND is always (as known from mathematics courses) evaluated before OR (binds more tightly).
Write it down in logic (truth table) if you are unsure.
3.3
Switch/case
Switch/Case
# switch . ps1
$short = @ { yes = " y " ; nope = " n " }
$ans = Read-Host
switch ( $ans ) {
yes { Write-Host " yes " }
nope { Write-Host " nope " ; break }
{ $short . ContainsKey ( " $ans " )} `
{ Write-Host $short [ $ans ] }
default { Write-Host " $ans `??? " }
}
Run example and see the difference between inputting yes, nope and nei.
In the example above {$short.ContainsKey("$ans")} checks if the content of $ans has an entry
(matches a key) in the associative array $short. Switch in PowerShell continues testing each case
unless it reads a break.
3.4
Where
Where/Where-Object
# where . ps1
Get-ChildItem | Where-Object { $_ . Length - gt 1 KB }
ITERATION
12
4
4.1
Iteration
For
For loop
# for . ps1
for ( $i =1; $i-le3 ; $i ++) {
Write-Host " $i "
}
# s o m e t h i n g more useful :
$file = Get-ChildItem
for ( $i =0; $i-lt$file . Count ; $i ++) {
if (!( Get-Item $file [ $i ]). PSIsContainer ) {
Write-Host $file [ $i ]. Name " is a file "
} else {
Write-Host $file [ $i ]. Name " is a directory "
}
}
Normally you would use ForEach instead of for since you can simplify the first loop above like
this:
ForEach ( $i in 1..3) {
Write-Host " $i "
}
ITERATION
4.2
While
While
# while . ps1
while ( $i - le 3) {
Write-Host $i
$i ++
}
# s o m e t h i n g more useful :
$file = Get-ChildItem
$i =0
while ( $i - lt $file . Count ) {
if (!( Get-Item $file [ $i ]). PSIsContainer ) {
Write-Host $file [ $i ]. Name " is a file "
} else {
Write-Host $file [ $i ]. Name " is a directory "
}
$i ++
}
4.3
Foreach
Foreach loop
# foreach . ps1
foreach ( $i in Get-ChildItem ) {
Write-Host $i . Name
}
# with a s s o c i a t i v e arrays
$user = @ {
" frodeh " = " Frode Haug " ;
" monicas " = " Monica Strand " ;
" ivarm " = " Ivar Moe "
}
foreach ( $key in $user . Keys ) {
Write-Host $user [ $key ]
}
13
MATH
14
# f o r e a c h - p i p e . ps1
foreach ( $i in $input ) {
$foo += @ ( $i )
}
Write-Host " size of foo is " $foo . Count
or
# f o r e a c h - o b j e c t - p i p e . ps1
$input | ForEach-O bject {
$foo += @ ( $_ )
}
Write-Host " size of foo is " $foo . Count
$ Get-ChildItem | ./ f o r e a c h - o b j e c t - p i p e . ps1
size of foo is 20
$input represents the pipeline and $_ the current object in the pipeline.
Math
Operators
Operator
+
*
/
%
# math . ps1
Write-Host " 3+5 is " (3+5)
Write-Host
Write-Host
Write-Host
Write-Host
Write-Host
"3+5
"3+5
"3+5
"3+5
"3+5
is" 3+5
is" (3+5)
is" $(3+5)
is (3+5)"
is $(3+5)"
Meaning
Add
Subtract
Multiply
Divide
Modulus
FUNCTIONS
15
Functions
Functions
# func . ps1
# declare :
function add ( $a , $b ) {
Write-Host " $a + $b is " ( $a + $b )
}
# use :
add 5.12 2.56
RegExp
Meaning
Any single character
One of these characters
Any one but these characters
A character in these ranges
REGEXP
16
Meaning
Group
OR
Anchoring:
Operator
Meaning
Beginning of line
End of line
Meaning
0 or 1 time
0 or more times
1 or more times
N times
At least N times
At least N but not more than M
7.1
PowerShell example
PowerShell example
POWERSHELL ONLY
17
# regexp . ps1
$input | ForEach-O bject {
if ( $_ - match
" [ A-Za-z0-9 . _- ]+ @ ([ A-Za-z0-9 .-]+) $ " ) {
Write-Host " Valid email " , $matches [0]
Write-Host " Domain is " , $matches [1]
} else {
Write-Host " Invalid email address ! "
}
}
When we use regular expressions inside scripts, it is very useful to be able to extract parts of the
match. We can do this by specifying the part with (part) and refer to it later using $matches[1],
$matches[2], etc. $matches[0] matches the entire expression.
http://www.regular-expressions.info/powershell.html
PowerShell only
Advanced stuff
See the complete Mastering PowerShell book at
http://powershell.com/cs/blogs/ebook/
for much more of what you can do with PowerShell
Credits
Credits
http://refcardz.dzone.com/refcardz/windows-powershell http://powershell.com/cs/blogs/ebook/ http://technet.microsoft.
com/en-us/library/ee692948.aspx http://www.techotopia.com/index.php/Windows_PowerShell_1.0_String_Quoting_and_Escape_