Contents
- Overview
- Getting Started
-
Examples
- Print out Processes
- Print out DLLs Loaded
- Semicolons and Return keyword are Optional
- Data Types
- Exception Handling
- Quotes
- PowerShell Subexpression
- Here Strings
- Closures, Functions, and Lambdas
- Arrays
- Parentheses
- Hash Tables
- Get-Member
- Pipe to Grid View
- New-Object
- Add-Member
- Add-Type
- Modules
- Scan for Name Value Pairs
- Template Engines
- Generate PowerShell Functions From C# Methods
- Calling PowerShell Functions from C#
- References
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