Windows PowerShell

 

Overview

* PowerShell is a glue language for distributed automation in Windows environment
* Leverage .NET framework
– Can be embedded in .NET applications
– Can embed .NET code directly in a PowerShell script
– Access C# class methods: [System.Math]::Pow(2,3)
* cmdlets are the basic units
* Pre-installed in Windows 7 and above

Getting Started

* Start PowerShell from Accessories -> Windows PowerShell menu folder
* Find version:

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.
 
PS C:\Users\Jimmy> $PSVersionTable
 
Name                           Value
----                           -----
CLRVersion                     2.0.50727.4984
BuildVersion                   6.1.7600.16385
PSVersion                      2.0
WSManStackVersion              2.0
PSCompatibleVersions           {1.0, 2.0}
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.1

* As calculator:

PS C:\Users\Jimmy> 2 + 2 * 3
8
PS C:\Users\Jimmy> "Hello World"
Hello World
PS C:\Users\Jimmy> [System.Math]::Pow(2,3)
8

* Use variable:

PS C:\Users\Jimmy> $a =  "hello"
PS C:\Users\Jimmy> $a.GetType()
 
IsPublic IsSerial Name    BaseType
-------- -------- ----    --------
True     True     String  System.Object

Run Scripts

* Set-ExecutionPolicy
Restricted (default): does not allow scripts or load config files
AllSigned: all scripts must be signed
RemoteSigned: remote scripts must be signed
Unrestricted: no restriction
Bypass: bypass all checks, even no warnings or prompts
Undefined: remove currently assigned execution policy from the current scope except those in Group Policy scope

PS C:\Windows\system32> mkdir c:\temp
 
    Directory: C:\
 
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----         4/19/2013   4:11 PM            temp
 
 
PS C:\Windows\system32> dir c:\temp
PS C:\Windows\system32> cd c:\temp
PS C:\temp> Set-ExecutionPolicy Unrestricted
 
PS C:\temp> Get-Content .\test.ps1
"Hello World"
PS C:\temp> .\test.ps1
Hello World
PS C:\temp>

PowerShell Editors

* PowerShell ISE (built-in)
* PowerGUI
* PowerShell Analyzer
* Professional PowerShell Script Editor (PowerSE)
* PrimalScript
* PowerShell Plus
* Visual Studio Plugins:
– NuGet
– StudioShell

Special Variables

$_ – Contains the current pipeline object, used in script blocks, filters, and the where statement.
$Args – Contains an array of the parameters passed to a function.
$Error – Contains objects for which an error occurred while being processed in a cmdlet.
$Home – Specifies the user’s home directory.
$PsHome – The directory where the Windows PowerShell is installed.

Special characters

* #: Comment character

# This is a comment

* %: is an alias for ForEach
* ?: is an alias for Where

1..10 | ? {$_ % 2 -eq 0} | % {$_* 2}
 
4
8
12
16
20

Set-Aliase

Set-Alias np "C:\Program Files (x86)\Notepad++\notepad++.exe"
np

Examples

Print out Processes

PS C:\temp> Get-Process | Where {$_.Handles -gt 750} | Sort PM -Descending
 
Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    979     211  1154988    1204292  1755 ...70.65   5168 firefox
    986      36   309332     327200   507 4,377.56   1688 svchost
   1208     117   159196     176844   542   108.06   9228 VpxClient
   1685      61   154912     128292   585 9,778.64   4508 FlashPlayerPlugin_11_6_602_180
   1477     105   107580     224284   563 1,144.64   5328 explorer
   2409      57    58104      89468   510   127.56   1728 svchost
   1003      58    45220      23216   290   278.49   9456 avgui
    824      49    42332      45240   632    43.27   1144 svchost
   1357      27    38520      45224   147   541.70   2028 avgrsa
    880      25    38184      30512   210   610.51   1140 csrss
    823      50    23032      38368   113    18.77   1872 svchost
    755      17    18516      42500   123    43.84   2136 nvxdsync
    942      38    15232      29568   146 1,090.90   5792 avgwdsvc
    993      30    13300      30016   133 1,989.00   3296 AcSvc
    944      31    12444      58312    84   227.12   1212 lsass
    857      16     4092      15068   123    11.95    772 csrss
   1103      10     2600       6712    53     1.45   2596 CamMute
   1435       0      424      10816   143               4 System

Print out DLLs Loaded

PS C:\temp> [System.AppDomain]::CurrentDomain.GetAssemblies() |
>> Where {$_.location} |
>> ForEach { Split-Path -Leaf $_.location } |
>> Sort
>>
Microsoft.PowerShell.Commands.Diagnostics.dll
Microsoft.PowerShell.Commands.Management.dll
Microsoft.PowerShell.Commands.Utility.dll
Microsoft.PowerShell.ConsoleHost.dll
Microsoft.PowerShell.Security.dll
Microsoft.WSMan.Management.dll
mscorlib.dll
System.Configuration.Install.dll
System.Core.dll
System.Data.dll
System.DirectoryServices.dll
System.dll
System.Management.Automation.dll
System.Management.dll
System.Transactions.dll
System.Xml.dll

Semicolons and Return keyword are Optional

PS C:\temp> function SayHello($p) {
>>     return "Hello $p"
>> }
>>
PS C:\temp> SayHello World
Hello World
PS C:\temp> function SayHello($p) {
>>     "Hello $p"
>> }
>>
PS C:\temp> SayHello World
Hello World

Data Types

PS C:\temp> $a = "Hello"
PS C:\temp> $a
Hello
PS C:\temp> $a = 1
PS C:\temp> $a += 1
PS C:\temp> $a
2
PS C:\temp> $a = 1,2,3
PS C:\temp> $a
1
2
3
PS C:\temp> [int]$a = 1
PS C:\temp> $a
1
PS C:\temp> [int]$a = "Hello"
Cannot convert value "Hello" to type "System.Int32". Error: "Input string was not in a correct format."
At line:1 char:8
+ [int]$a <<<<  = "Hello"
    + CategoryInfo          : MetadataError: (:) [], ArgumentTransformationMetadataException
    + FullyQualifiedErrorId : RuntimeException

* Strong typed parameters:

PS C:\temp> function Do-PrecisionCalculation {
>>     param (
>>         [Double]$Latitude,
>>         [Double]$Longitude
>>     )
>>
>>     [Math]::Sin($Latitude) * [Math]::Sin($Longitude)
>> }
>>
PS C:\temp> Do-PrecisionCalculation -Latitude 100 -Longitude 100
0.256406162496497

Exception Handling

* Supports try/catch/finally:

PS C:\Users\Jimmy> function div-by-zero($a, $b){
    try {
        $a/$b
        "Hello World"
    } catch {
        "Error caught: $($error[0])"
    } finally {
        "Finally, Hello World"
    }
}
 
PS C:\Users\Jimmy> div-by-zero -a 1 -b 0
Error caught: Attempted to divide by zero.
Finally, Hello World

Quotes

PS C:\temp>
PS C:\temp> "A string"
A string
PS C:\temp>
PS C:\temp> "A string with 'Quotes'"
A string with 'Quotes'
PS C:\temp>
PS C:\temp> "A string with `"Escaped Quotes`""
A string with "Escaped Quotes"
PS C:\temp>
PS C:\temp> $s = "PowerShell"
PS C:\temp> "A string with a variable: $s"
A string with a variable: PowerShell
PS C:\temp>
PS C:\temp> "A string with a quoted variable: '$s'"
A string with a quoted variable: 'PowerShell'
PS C:\temp>
PS C:\temp> 'Variables are not replaced inside single quotes: $s'
Variables are not replaced inside single quotes: $s

PowerShell Subexpression

PS C:\temp> $process = (Get-Process)[0]
PS C:\temp> $process.PM
6443008
PS C:\temp> "$process.PM"
System.Diagnostics.Process (AcDeskBandHlpr).PM
PS C:\temp> "$($process.PM)"
6443008

Here Strings

$name = "World"
 
$HereString = @"
This is a here-string
It can contain multiple lines
"Quotes don't need to be escaped"
Plus, you can include variables 'Hello $name'
"@
 
PS C:\Users\Jimmy> $HereString
This is a here-string
It can contain multiple lines
"Quotes don't need to be escaped"
Plus, you can include variables 'Hello World'

Closures, Functions, and Lambdas

* Closures:
– surrounded by {}
– executed by & operator

PS C:\temp> $n = "PowerShell"
PS C:\temp> $closure = {"Hello $n"}
PS C:\temp> & $closure
Hello PowerShell
PS C:\temp>

* Functions (closures or script blocks with names):

PS C:\temp> function Add5 ($num) {
>>     $num + 5
>> }
>>
PS C:\temp> Add5 5
10

* Lambdas (closures or script blocks without names):

PS C:\temp> $add5 = {param($num) $num + 5}
PS C:\temp> & $add5 5
10

Arrays

* Same as .NET System.Array

$animals = "cat", "dog", "fish"
$animals.GetType()
$animals
 
IsPublic IsSerial Name       BaseType                                       
-------- -------- ----       --------                                       
True     True     Object[]   System.Array                                   
cat
dog
fish

* Empty array:

$animals = @()
$animals.Count
 
0

* Add an array item:

$animals = "cat", "dog", "fish"
$animals += "bird"
$animals
 
cat
dog
fish
bird

* Access an array item:

$animals = "cat", "dog", "fish"
$animals[1]

* Array slicing:

$animals = "cat", "dog", "fish"
$animals[0..1]
 
cat
dog

* Finding array elements:

$animals = "cat", "dog", "fish"
$animals -ne 'cat'
 
dog
fish
 
$animals = "cat", "dog", "fish"
#$animals -ne 'cat'
$animals -like "*o*"
 
dog

* Reversing an array:

$animals = "cat", "dog", "fish"
[array]::Reverse($animals)
$animals
 
fish
dog
cat

* Assign array values to multiple variables

$items = "One", "Two", "Three", 1, 2, 3
$items
 
$one, $two, $three, $numbers = $items
 
$one
$two
$three
$numbers
 
One
Two
Three
1
2
3
One
Two
Three
1
2
3

Parentheses

* Don't use parentheses to pass parameters to a function:
function Test($p1, $p2) {
    '$p1' + "is: " + $p1
    '$p2' + "is: " + $p2
    ""
}
 
Test (1, 2) # Actually passing in an array
 
Test 1 2
 
$p1is: 1 2
$p2is: 
 
$p1is: 1
$p2is: 2

Hash Tables

# Empty hash map
$h = @{}
$h.Count
 
# Assign elements
$h.Item1 = 1
$h.Item2 = 2
 
# Initialize hash map
$h = @{Item1=1; Item2=2}
 
# Access hash map
$h
$h.Item1
$h.Item2
 
# Concatenate hash tables
$h1 = @{a=1;b=2}
$h2 = @{c=3;d=4}
$h = $h1 + $h2
$h

Get-Member

* Returns the members (properties and methods) of objects at the command line.

New-Object Net.Webclient | Get-Member -MemberType Property
 
   TypeName: System.Net.WebClient
 
Name                  MemberType Definition                                                               
----                  ---------- ----------                                                               
BaseAddress           Property   System.String BaseAddress {get;set;}                                     
CachePolicy           Property   System.Net.Cache.RequestCachePolicy CachePolicy {get;set;}               
Container             Property   System.ComponentModel.IContainer Container {get;}                        
Credentials           Property   System.Net.ICredentials Credentials {get;set;}                           
Encoding              Property   System.Text.Encoding Encoding {get;set;}                                 
Headers               Property   System.Net.WebHeaderCollection Headers {get;set;}                        
IsBusy                Property   System.Boolean IsBusy {get;}                                             
Proxy                 Property   System.Net.IWebProxy Proxy {get;set;}                                    
QueryString           Property   System.Collections.Specialized.NameValueCollection QueryString {get;set;}
ResponseHeaders       Property   System.Net.WebHeaderCollection ResponseHeaders {get;}                    
Site                  Property   System.ComponentModel.ISite Site {get;set;}                              
UseDefaultCredentials Property   System.Boolean UseDefaultCredentials {get;set;}

Pipe to Grid View

New-Object Net.Webclient | Get-Member | Out-GridView

New-Object

* Creates an instance of .NET object
* Examples:
– Open IE and go to google.com:

$ie = New-Object -ComObject InternetExplorer.Application
$ie.Navigate2("http://www.google.com")
$ie.Visible = $true

– Create a new PowerShell object:

$obj = New-Object PSObject -Property @{Name="John";Age="10"}
$obj.GetType()
$obj
 
IsPublic IsSerial Name             BaseType                                       
-------- -------- ----             --------                                       
True     False    PSCustomObject   System.Object                                  
 
Name : John
Age  : 10

– Use .NET framework:

$wc = New-Object Net.WebClient
[xml]$resp = $wc.DownloadString("http://feeds.feedburner.com/DevelopmentInABlink")
$resp.rss.channel.item | ForEach {$_.Title}
 
PowerShell Automation
Creating a PowerShell Translate Function
How to run PowerShell from node.js
Using PowerShell to find all the years since you were born where the four digits were unique
Use PowerShell to find the free space on the volume behind an SMB file share
Learn one PowerShell command
I’ll be presenting on PowerShell at the Philly Code Camp
Building GUI Applications in PowerShell
Honorary PowerShell Scripting Guy
PowerShell kv – save snippets of text that you can later find and copy to your clipboard

Add-Member

$s = "Hello World" | Add-Member -PassThru ScriptProperty Reverse {$this[$this.Length..0] -join ""}
$s
$s.Reverse
 
Hello World
dlroW olleH

Add-Type

* Compile C# on the fly:

Add-Type -TypeDefinition @"
public class MyMathClass {
    public int Add(int n1, int n2) {
        return n1 + n2;
    }
}
"@
 
$obj = New-Object MyMathClass
$obj.GetType()
$obj | Get-Member
 
1..5 | ForEach {$obj.Add($_,$_)}

Modules

TODO.

Scan for Name Value Pairs

$regex = "(?<name>\w+)\s*=\s*(?<value>.*)((?=\W$)|\z)"
 
dir c:\temp *.txt | Select-String $regex |
    ForEach {
        $fn = $_.Path
        ForEach($match in $_.Matches) {
            $obj = New-Object PSObject -Property @{
                FileName = $fn
                Name = $match.Groups["name"].Value
                Value = $match.Groups["value"].Value
            }
        }
        $obj
    }

Template Engines

* Process templates and content to produce output
TODO

Generate PowerShell Functions From C# Methods

* MyMath C# class:

$code = @"
public class MyMath {
    public int MyAdd(int n1, int n2) {
        return n1 + n2;
    }
 
    public int MySubstract (int n1, int n2) {
        return n1 - n2;
    }
}
"@
 
Add-Type -TypeDefinition $code
 
[MyMath].GetMethods() 
 
[MyMath].GetMethods() |
    ForEach {
        $_.GetParameters()
    }

* PowerShell Wrapper:

$MyMath = New-Object MyMath
function Invoke-MyAdd ($n1, $n2) {$MyMath.MyAdd($n1, $n2)}
function Invoke-MySubstract ($n1, $n2) {$MyMath.MySubstract($n1, $n2)}
 
Invoke-MyAdd 1 3
 
1..10|
ForEach {Invoke-MyAdd $_ $_}

* Note that once type is added, it can not be removed until you restart PowerShell

Calling PowerShell Functions from C#

TODO

 

References

* Windows PowerShell for Developers

This entry was posted in PowerShell and tagged . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *


*

This site uses Akismet to reduce spam. Learn how your comment data is processed.