From 083eb1c4a5ef1da2249ad9640bc2f62cf9f95af0 Mon Sep 17 00:00:00 2001 From: Laoujin Date: Fri, 27 Nov 2015 00:19:06 +0100 Subject: [PowerShell/en] intro --- powershell.html.markdown | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 powershell.html.markdown (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown new file mode 100644 index 00000000..5ec18afb --- /dev/null +++ b/powershell.html.markdown @@ -0,0 +1,56 @@ +--- +category: tool +tool: powershell +contributors: + - ["Wouter Van Schandevijl", "https://github.com/laoujin"] +filename: LearnPowershell.ps1 +--- + +PowerShell is the Windows scripting language and configuration management framework from Microsoft built on the .NET Framework. Windows 7 and up ship with PowerShell. +Nearly all examples below can be a part of a shell script or executed directly in the shell. + +A key difference with Bash is that it is mostly objects that you manipulate rather than plain text. + +[Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx) + +```powershell +# As you already figured, comments start with # + +# Simple hello world example: +echo Hello world! +# echo is an alias for Write-Output (=cmdlet) +# Most cmdlets and functions follow the Verb-Noun naming convention + +# Each command starts on a new line, or after semicolon: +echo 'This is the first line'; echo 'This is the second line' + +# Declaring a variable looks like this: +$Variable="Some string" +# Or like this: +$Variable1 = "Another string" + +# Using the variable: +echo $Variable +echo "$Variable" +echo '$($Variable + '1')' +echo @" +This is a Here-String +$Variable +"@ +# Note that ' (single quote) won't expand the variables! +# Here-Strings also work with single quote + +# Builtin variables: +# There are some useful builtin variables, like +echo "Booleans: $TRUE and $FALSE" +echo "Empty value: $NULL" +echo "Last program's return value: $?" +echo "Script's PID: $PID" +echo "Number of arguments passed to script: $#" +echo "All arguments passed to script: $Args" +echo "Script's arguments separated into different variables: $1 $2..." + +# Reading a value from input: +$Name = Read-Host "What's your name?" +echo "Hello, $Name!" +[int]$Age = Read-Host "What's your age?" \ No newline at end of file -- cgit v1.2.3 From 4d44e241d72b160c31e74db29ff389371d35579f Mon Sep 17 00:00:00 2001 From: Laoujin Date: Fri, 27 Nov 2015 01:07:45 +0100 Subject: [PowerShell/en] execution-policy, builtin variables, configure your shell --- powershell.html.markdown | 60 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 50 insertions(+), 10 deletions(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index 5ec18afb..2a7deee1 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -13,6 +13,22 @@ A key difference with Bash is that it is mostly objects that you manipulate rath [Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx) +If you are uncertain about your environment: +```powershell +Get-ExecutionPolicy -List +Set-ExecutionPolicy AllSigned +# Execution policies include: +# - Restricted: Scripts won't run. +# - RemoteSigned: Downloaded scripts run only if signed by a trusted publisher. +# - AllSigned: Scripts need to be signed by a trusted publisher. +# - Unrestricted: Run all scripts. +help about_Execution_Policies # for more info + +# Current PowerShell version: +$PSVersionTable +``` + +The tutorial starts here: ```powershell # As you already figured, comments start with # @@ -25,17 +41,18 @@ echo Hello world! echo 'This is the first line'; echo 'This is the second line' # Declaring a variable looks like this: -$Variable="Some string" +$aString="Some string" # Or like this: -$Variable1 = "Another string" +$aNumber = 5 # Using the variable: -echo $Variable -echo "$Variable" -echo '$($Variable + '1')' +echo $aString +echo "Interpolation: $aString" +echo "`$aString has length of $($aString.length)" +echo '$aString' echo @" This is a Here-String -$Variable +$aString "@ # Note that ' (single quote) won't expand the variables! # Here-Strings also work with single quote @@ -45,12 +62,35 @@ $Variable echo "Booleans: $TRUE and $FALSE" echo "Empty value: $NULL" echo "Last program's return value: $?" +echo "Exit code of last run Windows-based program: $LastExitCode" +echo "The last token in the last line received by the session: $$" +echo "The first token: $^" echo "Script's PID: $PID" -echo "Number of arguments passed to script: $#" -echo "All arguments passed to script: $Args" -echo "Script's arguments separated into different variables: $1 $2..." +echo "Full path of current script directory: $PSScriptRoot" +echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path +echo "FUll path of current directory: $Pwd" +echo "Bound arguments in a function, script or code block: $PSBoundParameters" +echo "Unbound arguments: $($Args -join ', ')." ######################## MOVE THIS TO FUNCTIONS +# More builtins: `help about_Automatic_Variables` # Reading a value from input: $Name = Read-Host "What's your name?" echo "Hello, $Name!" -[int]$Age = Read-Host "What's your age?" \ No newline at end of file +[int]$Age = Read-Host "What's your age?" + + + + +``` + + +Configuring your shell +```powershell +# $Profile is the full path for your `Microsoft.PowerShell_profile.ps1` +# All code there will be executed when the PS session starts +if (-not (Test-Path $Profile)) { + New-Item -Type file -Path $Profile -Force + notepad $Profile +} +# More info: `help about_profiles` +``` \ No newline at end of file -- cgit v1.2.3 From bc47915c8f09fc586e47fd37fef76f6d27a0a8b8 Mon Sep 17 00:00:00 2001 From: Laoujin Date: Fri, 27 Nov 2015 02:37:30 +0100 Subject: [PowerShell/en] control-flow, pipeline, getting help --- powershell.html.markdown | 96 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index 2a7deee1..be802916 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -28,6 +28,18 @@ help about_Execution_Policies # for more info $PSVersionTable ``` +Getting help: +```powershell +# Find commands +Get-Command about_* # alias: gcm +Get-Command -Verb Add +Get-Alias ps +Get-Alias -Definition Get-Process + +Get-Help ps | less # alias: help +ps | Get-Member # alias: gm +``` + The tutorial starts here: ```powershell # As you already figured, comments start with # @@ -44,8 +56,10 @@ echo 'This is the first line'; echo 'This is the second line' $aString="Some string" # Or like this: $aNumber = 5 +$aList = 1,2,3,4,5 +$aHashtable = @{name1='val1'; name2='val2'} -# Using the variable: +# Using variables: echo $aString echo "Interpolation: $aString" echo "`$aString has length of $($aString.length)" @@ -78,7 +92,87 @@ $Name = Read-Host "What's your name?" echo "Hello, $Name!" [int]$Age = Read-Host "What's your age?" +# Control Flow +# We have the usual if structure: +if ($Age -is [string]) { + echo 'But.. $Age cannot be a string!' +} elseif ($Age -lt 12 -and $Age -gt 0) { + echo 'Child (Less than 12. Greater than 0)' +} else { + echo 'Adult' +} +# Switch statements are more powerfull compared to most languages +$val = "20" +switch($val) { + { $_ -eq 42 } { "The answer equals 42"; break } + '20' { "Exactly 20"; break } + { $_ -like 's*' } { "Case insensitive"; break } + { $_ -clike 's*'} { "clike, ceq, cne for case sensitive"; break } + { $_ -notmatch '^.*$'} { "Regex matching. cnotmatch, cnotlike, ..."; break } + { 'x' -contains 'x'} { "FALSE! -contains is for lists!"; break } + default { "Others" } +} + +# The classic for +for($i = 1; $i -le 10; $i++) { + "Loop number $i" +} +# Or shorter +1..10 | % { "Loop number $_" } + +# PowerShell also offers +foreach ($var in 'val1','val2','val3') { echo $var } +# while () {} +# do {} while () +# do {} until () + + +# List files and directories in the current directory +ls # or `dir` +cd ~ # goto home + +Get-Alias ls # -> Get-ChildItem +# Uh!? These cmdlets have generic names because unlike other scripting +# languages, PowerShell does not only operate in the current directory. +cd HKCU: # go to the HKEY_CURRENT_USER registry hive + +# Get all providers in your session +Get-PSProvider + +# Cmdlets have parameters that control their execution: +Get-ChildItem -Filter *.txt -Name # Get just the name of all txt files +# Only need to type as much of a parameter name until it is no longer ambiguous +ls -fi *.txt -n # -f is not possible because -Force also exists +# Use `Get-Help Get-ChildItem -Full` for a complete overview + +# Results of the previous cmdlet can be passed to the next as input. +# grep cmdlet filters the input with provided patterns. +# `$_` is the current object in the pipeline object. +ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt +ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html + +# If you get confused in the pipeline use `Get-Member` for an overview +# of the available methods and properties of the pipelined objects: +ls | Get-Member +Get-Date | gm + +# ` is the line continuation character. Or end the line with a | +Get-Process | Sort-Object ID -Descending | Select-Object -First 10 Name,ID,VM ` + | Stop-Process -WhatIf + +Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List + +# Use % as a shorthand for ForEach-Object +(a,b,c) | ForEach-Object ` + -Begin { "Starting"; $counter = 0 } ` + -Process { "Processing $_"; $counter++ } ` + -End { "Finishing: $counter" } + +# Get-Process as a table with three columns +# The third column is the value of the VM property in MB and 2 decimal places +# Computed columns can be written more succinctly as: `@{n='lbl';e={$_}` +ps | Format-Table ID,Name,@{name='VM(MB)';expression={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize ``` -- cgit v1.2.3 From 0b7c612c3ed5c82b05bca22bcf3622e37fe55581 Mon Sep 17 00:00:00 2001 From: Laoujin Date: Fri, 27 Nov 2015 03:49:34 +0100 Subject: [PowerShell/en] IO, Interesting Projects, Not Covered, Exception Handling, UseFull stuff, max line 80. --- powershell.html.markdown | 144 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 129 insertions(+), 15 deletions(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index be802916..6f38c45c 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -6,10 +6,14 @@ contributors: filename: LearnPowershell.ps1 --- -PowerShell is the Windows scripting language and configuration management framework from Microsoft built on the .NET Framework. Windows 7 and up ship with PowerShell. -Nearly all examples below can be a part of a shell script or executed directly in the shell. +PowerShell is the Windows scripting language and configuration management +framework from Microsoft built on the .NET Framework. Windows 7 and up ship +with PowerShell. +Nearly all examples below can be a part of a shell script or executed directly +in the shell. -A key difference with Bash is that it is mostly objects that you manipulate rather than plain text. +A key difference with Bash is that it is mostly objects that you manipulate +rather than plain text. [Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx) @@ -38,6 +42,10 @@ Get-Alias -Definition Get-Process Get-Help ps | less # alias: help ps | Get-Member # alias: gm + +Show-Command Get-EventLog # Display GUI to fill in the parameters + +Update-Help # Run as admin ``` The tutorial starts here: @@ -49,20 +57,21 @@ echo Hello world! # echo is an alias for Write-Output (=cmdlet) # Most cmdlets and functions follow the Verb-Noun naming convention -# Each command starts on a new line, or after semicolon: +# Each command starts on a new line, or after a semicolon: echo 'This is the first line'; echo 'This is the second line' # Declaring a variable looks like this: $aString="Some string" # Or like this: -$aNumber = 5 +$aNumber = 5 -as [double] $aList = 1,2,3,4,5 +$aString = $aList -join '--' # yes, -split exists also $aHashtable = @{name1='val1'; name2='val2'} # Using variables: echo $aString echo "Interpolation: $aString" -echo "`$aString has length of $($aString.length)" +echo "`$aString has length of $($aString.Length)" echo '$aString' echo @" This is a Here-String @@ -84,15 +93,14 @@ echo "Full path of current script directory: $PSScriptRoot" echo 'Full path of current script: ' + $MyInvocation.MyCommand.Path echo "FUll path of current directory: $Pwd" echo "Bound arguments in a function, script or code block: $PSBoundParameters" -echo "Unbound arguments: $($Args -join ', ')." ######################## MOVE THIS TO FUNCTIONS +echo "Unbound arguments: $($Args -join ', ')." # More builtins: `help about_Automatic_Variables` -# Reading a value from input: -$Name = Read-Host "What's your name?" -echo "Hello, $Name!" -[int]$Age = Read-Host "What's your age?" +# Inline another file (dot operator) +. .\otherScriptName.ps1 -# Control Flow + +### Control Flow # We have the usual if structure: if ($Age -is [string]) { echo 'But.. $Age cannot be a string!' @@ -127,7 +135,14 @@ foreach ($var in 'val1','val2','val3') { echo $var } # do {} while () # do {} until () +# Exception handling +try {} catch {} finally {} +try {} catch [System.NullReferenceException] { + echo $_.Exception | Format-List -Force +} + +### Providers # List files and directories in the current directory ls # or `dir` cd ~ # goto home @@ -140,6 +155,8 @@ cd HKCU: # go to the HKEY_CURRENT_USER registry hive # Get all providers in your session Get-PSProvider + +### Pipeline # Cmdlets have parameters that control their execution: Get-ChildItem -Filter *.txt -Name # Get just the name of all txt files # Only need to type as much of a parameter name until it is no longer ambiguous @@ -171,10 +188,96 @@ Get-EventLog Application -After (Get-Date).AddHours(-2) | Format-List # Get-Process as a table with three columns # The third column is the value of the VM property in MB and 2 decimal places -# Computed columns can be written more succinctly as: `@{n='lbl';e={$_}` -ps | Format-Table ID,Name,@{name='VM(MB)';expression={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize +# Computed columns can be written more verbose as: +# `@{name='lbl';expression={$_}` +ps | Format-Table ID,Name,@{n='VM(MB)';e={'{0:n2}' -f ($_.VM / 1MB)}} -autoSize + + +### Functions +# The [string] attribute is optional. +function foo([string]$name) { + echo "Hey $name, have a function" +} + +# Calling your function +foo "Say my name" + +# Functions with named parameters, parameter attributes, parsable documention +<# +.SYNOPSIS +Setup a new website +.DESCRIPTION +Creates everything your new website needs for much win +.PARAMETER siteName +The name for the new website +.EXAMPLE +New-Website -Name FancySite -Po 5000 +New-Website SiteWithDefaultPort +New-Website siteName 2000 # ERROR! Port argument could not be validated +('name1','name2') | New-Website -Verbose +#> +function New-Website() { + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline=$true, Mandatory=$true)] + [Alias('name')] + [string]$siteName, + [ValidateSet(3000,5000,8000)] + [int]$port = 3000 + ) + BEGIN { Write-Verbose 'Creating new website(s)' } + PROCESS { echo "name: $siteName, port: $port" } + END { Write-Verbose 'Website(s) created' } +} + +### It's all .NET +# A PS string is in fact a .NET System.String +# All .NET methods and properties are thus available +'string'.ToUpper().Replace('G', 'ggg') +# Or more powershellish +'string'.ToUpper() -replace 'G', 'ggg' +# Unsure how that .NET method is called again? +'string' | gm + +# Syntax for calling static .NET methods +[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') + +# Note that .NET functions MUST be called with parentheses +# while PS functions CANNOT be called with parentheses +$writer = New-Object System.IO.StreamWriter($path, $true) +$writer.Write([Environment]::NewLine) +$write.Dispose() + +### IO +# Reading a value from input: +$Name = Read-Host "What's your name?" +echo "Hello, $Name!" +[int]$Age = Read-Host "What's your age?" + +# Test-Path, Split-Path, Join-Path, Resolve-Path +# Get-Content filename # returns a string[] +# Set-Content, Add-Content, Clear-Content +Get-Command ConvertTo-*,ConvertFrom-* + + +### Useful stuff +# Refresh your PATH +$env:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User") +# Find Python in path +$env:PATH.Split(";") | Where-Object { $_ -like "*python*"} + +# Change working directory without having to remember previous path +Push-Location c:\temp # change working directory to c:\temp +Pop-Location # change back to previous working directory + +# Unblock a directory after download +Get-ChildItem -Recurse | Unblock-File + +# Open Windows Explorer in working directory +ii . ``` @@ -187,4 +290,15 @@ if (-not (Test-Path $Profile)) { notepad $Profile } # More info: `help about_profiles` -``` \ No newline at end of file +``` + +Interesting Projects +* [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell videos +* [PSake](https://github.com/psake/psake) Build automation tool +* [Pester](https://github.com/pester/Pester) BDD Testing Framework + +Not covered +* WMI: Windows Management Intrumentation (Get-CimInstance) +* Multitasking: Start-Job -scriptBlock {...}, +* Code Signing +* Remoting (Enter-PSSession/Exit-PSSession; Invoke-Command) \ No newline at end of file -- cgit v1.2.3 From 3cbcf0e98368d58b708fd945f96d7996386f57ed Mon Sep 17 00:00:00 2001 From: Laoujin Date: Fri, 27 Nov 2015 04:05:53 +0100 Subject: [PowerShell/en] More usefull snippets and interesting projects --- powershell.html.markdown | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index 6f38c45c..ce9cfa72 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -278,6 +278,17 @@ Get-ChildItem -Recurse | Unblock-File # Open Windows Explorer in working directory ii . + +# Any key to exit +$host.UI.RawUI.ReadKey() +return + +# Create a shortcut +$WshShell = New-Object -comObject WScript.Shell +$Shortcut = $WshShell.CreateShortcut($link) +$Shortcut.TargetPath = $file +$Shortcut.WorkingDirectory = Split-Path $file +$Shortcut.Save() ``` @@ -290,12 +301,18 @@ if (-not (Test-Path $Profile)) { notepad $Profile } # More info: `help about_profiles` +# For a more usefull shell, be sure to check the project PSReadLine below ``` Interesting Projects -* [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell videos +* [Channel9](https://channel9.msdn.com/Search?term=powershell%20pipeline#ch9Search&lang-en=en) PowerShell tutorials +* [PSGet](https://github.com/psget/psget) NuGet for PowerShell +* [PSReadLine](https://github.com/lzybkr/PSReadLine/) A bash inspired readline implementation for PowerShell (So good that it now ships with Windows10 by default!) +* [Posh-Git](https://github.com/dahlbyk/posh-git/) Fancy Git Prompt (Recommended!) * [PSake](https://github.com/psake/psake) Build automation tool * [Pester](https://github.com/pester/Pester) BDD Testing Framework +* [Jump-Location](https://github.com/tkellogg/Jump-Location) Powershell `cd` that reads your mind +* [PowerShell Community Extensions](http://pscx.codeplex.com/) (Dead) Not covered * WMI: Windows Management Intrumentation (Get-CimInstance) -- cgit v1.2.3 From 276390e4583ffe471fd90d527fd0ef1c96510119 Mon Sep 17 00:00:00 2001 From: Wouter Van Schandevijl Date: Fri, 27 Nov 2015 05:44:22 +0100 Subject: [Powershell/en] Deleted a left-over from the bash turorial --- powershell.html.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index ce9cfa72..9c521b27 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -164,7 +164,6 @@ ls -fi *.txt -n # -f is not possible because -Force also exists # Use `Get-Help Get-ChildItem -Full` for a complete overview # Results of the previous cmdlet can be passed to the next as input. -# grep cmdlet filters the input with provided patterns. # `$_` is the current object in the pipeline object. ls | Where-Object { $_.Name -match 'c' } | Export-CSV export.txt ls | ? { $_.Name -match 'c' } | ConvertTo-HTML | Out-File export.html @@ -318,4 +317,4 @@ Not covered * WMI: Windows Management Intrumentation (Get-CimInstance) * Multitasking: Start-Job -scriptBlock {...}, * Code Signing -* Remoting (Enter-PSSession/Exit-PSSession; Invoke-Command) \ No newline at end of file +* Remoting (Enter-PSSession/Exit-PSSession; Invoke-Command) -- cgit v1.2.3 From 90a7e8ac4910e0ab754ce1801d6743fb6c70eaba Mon Sep 17 00:00:00 2001 From: Laoujin Date: Sat, 28 Nov 2015 19:44:24 +0100 Subject: [PowerShell/en] Markdown ```powershell didn't render properly --- powershell.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'powershell.html.markdown') diff --git a/powershell.html.markdown b/powershell.html.markdown index ce9cfa72..70935993 100644 --- a/powershell.html.markdown +++ b/powershell.html.markdown @@ -18,7 +18,7 @@ rather than plain text. [Read more here.](https://technet.microsoft.com/en-us/library/bb978526.aspx) If you are uncertain about your environment: -```powershell +``` Get-ExecutionPolicy -List Set-ExecutionPolicy AllSigned # Execution policies include: @@ -33,7 +33,7 @@ $PSVersionTable ``` Getting help: -```powershell +``` # Find commands Get-Command about_* # alias: gcm Get-Command -Verb Add @@ -49,7 +49,7 @@ Update-Help # Run as admin ``` The tutorial starts here: -```powershell +``` # As you already figured, comments start with # # Simple hello world example: @@ -293,7 +293,7 @@ $Shortcut.Save() Configuring your shell -```powershell +``` # $Profile is the full path for your `Microsoft.PowerShell_profile.ps1` # All code there will be executed when the PS session starts if (-not (Test-Path $Profile)) { -- cgit v1.2.3