power shell voor developers
TRANSCRIPT
KEEP CALMand
LEARNPOWERSHELL
YouTube: https://www.youtube.com/watch?v=V5Gjx4jM91A
QuintorJAVA
.NET
MOBILE
GRONINGENAMERSFOORTDEN HAAG
112 EMPLOYEESATLASSIANMS TFS
AGILE/SCRUM
ANALYSE
Employees
Januari 2006
Januari 2007
Januari 2008
Januari 2009
Januari 2010
Januari 2011
Januari 2012
Januari 2013
Januari 2014
Januari 2015
Januari 2016
0
20
40
60
80
100
120
Groningen Amersfoort Den Haag
KEEP CALMand
LEARNPOWERSHELL
Jeroen Swart.NET [email protected]
• Developer >= 1996• Mainframe/assembler, Microsoft/C++, .NET/C#• .NET >= 2001• Quintor >= 2011• .NET competentie• ALM & .NET ontwikkelstraat
REPL
DSCRemote
PowerShell
Verb
Commands
Build &Release Management
Functions
PowerShell
Package Management
Modules
NuGet
Strings
Pipeline
TasksTFS
Scripts
Chocolatey
PowerShell Gallery
Objects
Arrays
> _−REPL (Read Evaluate Print Loop)−.NET−Commands−Parameters−Objecten−Command pipeline
Show-Code
> Commands−[Verb]-[Prefix][Noun]
−Verb: Get, New, Update, … (Get-Verb)
−Prefix: VM, AD, Azure, Sql, …−Noun: Switch, User, Website, Database− Get-Service− Get-VMSwitch− New-ADUser− Start-AzureWebsite− Backup-SqlDatabase
> Command pipeline−Get-Process | Sort ProcessName | Select *
−Select-Object select−Sort-Object sort−Where-Object where, ?−ForEach-Object foreach, %
> Select-Object−Specify which properties to return
− Select ProcessName,Description− Select *
−Specify how many objects to return− Select –First 5− Select –First 5 –Skip 5− Select –Last 10
− Get-Process | Select ProcessName,Description –First 10
> Sort-Object−Specify order of objects
− Sort ProcessName
−Specify direction− Sort ProcessName -Descending
−Get-Process | Sort ProcessName,Description
> Where-Object−Filter objects by property
− Where -Property ProcessName -EQ 'powershell'
−Filter objects using script− Where { $_.ProcessName -eq 'powershell' }
− Get-Process |? { $_.ProcessName -like 'po*' }
> ForEach-Object−Repeat for each object
− ForEach { Write-Host $_.ProcessName }
− Get-Process |% { Write-Host "$($_.ProcessName)" }
> Command pipeline−Measure-Object−Group-Object−Compare-Object−Tee-Object
> Format-*−Format-Table (ft)
− -AutoSize (ft –a)−Format-List (fl)−Format-Wide (fw)
− -Column (fw –c 3)
−Get-Command format-*
> Out-*−Out-Default−Out-File−Out-Null−Out-String−Out-GridView (ogv)
−Get-Command out-*
> ConvertTo-* / ConvertFrom-*−ConvertTo-Json, ConvertFrom-Json−ConvertTo-Xml (, Get-Content)−ConvertTo-Csv, ConvertFrom-Csv−ConvertTo-Html
−Get-Command convertto-*,convertfrom-*
> Advanced pipeline−-PassThru−Multiline with `−Multi-command on single line with ;−Select @{ Name = $_.Name; Type = 'Foo' }
− Force expression evaluation using brackets ()
Show-Code
> Hosts−Console−ISE (Integrated Script Environment)−Visual Studio Extension (2015, 2013, 2012)
−Visual Studio Code Extension−PowerGUI−PowerShell Plus−Custom−[insert your application name here]
> Host environment−Get-Variable−$Host−$Profile−$PSVersionTable
> $Host−Console
−ISE
> $Profile−Current user / All users−Current host / All hosts−$profile
− Current user, current host−$profile.AllUsersAllHosts−$profile.AllUsersCurrentHosts−$profile.CurrentUsersAllHosts−$profile.CurrentUsersCurrentHost
$profile.AllUsersAllHosts C:\Windows\System32\WindowsPowerShell\v1.0\profile.ps1
$profile.AllUsersCurrentHostsC:\Windows\System32\WindowsPowerShell\v1.0\Microsoft.PowerShell_profile.ps1
$profile.CurrentUsersAllHostsC:\Users\jswart\Documents\WindowsPowerShell\profile.ps1
$profile.CurrentUsersCurrentHostC:\Users\jswart\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
$profile (console)C:\Users\jswart\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
$profile (ISE)C:\Users\jswart\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
> $Profile$global:CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent()
function prompt{ $Host.UI.RawUI.WindowTitle = "$($CurrentUser.Name) - $(Get-Location)"
Write-Host 'PS >' -NoNewline return ' '}
> $PSVersionTableName Value---- -----PSVersion 5.0.10586.122PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}BuildVersion 10.0.10586.122CLRVersion 4.0.30319.42000WSManStackVersion 3.0PSRemotingProtocolVersion 2.3SerializationVersion 1.1.0.1
> Strings−Literals
− 'Name: $Name'− "Name: $Name"
−Format− 'Name: {0}' –f $Name
−Expression− "Name: $user.Name"− "Name: $($user.Name)"
Name: $NameName: Jeroen
Name: Jeroen
Name: Hashtable.NameName: Jeroen
> Strings & regular expressions−Match
− 'PowerShell' –match 'sh'− 'PowerShell' –match '^P'− 'PowerShell' –match 'P$‘− 'PowerShell' –cmatch
'p$'
−Replace− 'PowerShell' -replace 'e','E'
TrueTrueFalseFalse
PowErShEll
> Arrays & objects−Command output is array or object−When Parameter type is Array, provide either array or single object as value
> Arrays−$a = 1,2−$a = @(1)−$a = @()−$a = 1..5−$a += 6−$a.GetType() -> System.Array
− $a.Length− $a.Contains(1)− $a[0]
> Objects (HashTable)−$o = @{}−$o = @{ Name = 'me' }−$o = @{
Name = 'me'PowerShell = $true
}−$o = @{ Name = 'me'; PowerShell = $true }
> Objects (PSCustomObject)
$o = New-Object PSCustomObject ` | Add-Member -MemberType NoteProperty -Name 'Name' -Value 'me' -PassThru ` | Add-Member -MemberType NoteProperty -Name 'PowerShell' -Value $true -PassThru
> Objects−$o.Name−$o.'Name'−$o = @{
Name = 'me'PowerShell = $true
}−$o = @{ Name = 'me'; PowerShell = $true }
> Scripts−Collection of commands−Conditional statements (if/else, etc.)−Parameters−Output−Execute using . Or &−Execute using full or relative path (.\). .\DoSomethingSmart.ps1
. '.\DoSomethingSmart.ps1'
> Scripts – if/else
if ($condition) {
}
elseif ($otherCondition) {
}
else {
}
if (Test-Path -Path $path) {}
if (Get-Service 'MSSQL*') {}
Basic syntax Using commands returning a boolean
Using other commands
if ($name -eq 'PowerShell' ) {}
Using logical operatorsif ($condition -eq $true) {}
Using explicit conditions
> Scripts – if/else− -eq, -ne− -lt, -gt, -le, -ge− -like, -match, -notlike, -notmatch− -contains, -in, -notcontains, -notin− And their case-sensitive version (-ceq, -clike, etc.)− And their (explicit) case-insensitive version (-ieq, -ilike, etc.)
− -not, -or, -and, -xor− And their binary version (-bnot, -bor, etc.)
− -is, -isnot
> Scripts – switch/case
switch ($value) {
1 { }
2 { }
default { }
}
switch ($value) { '1' { }
'2' { }
default { }
}
switch ($value) { { $_ -eq 1 } { }
{ $_ -in 2,3 } { }
{ $_ -like '4*' } { }
{ $_ -match '^5' } { }
default { }
}
Basic syntax
Using strings
Using expressions
> Scripts – foreach
foreach ($item in $items) {
# use $item
}
$items |% {
# use $_
}
Basic syntax
Alternative
> Scripts – for
for ($index = 0; $index -lt 10; $index++) {
# use $items[$index]
}
Basic syntax
> Scripts – try/catch try { throw 'Serious error'
throw [InvalidOperationException]'Serious error'
}
catch [InvalidOperationException] {
write-host 'InvalidOperationException'
}
catch {
}
finally {
}
> Scripts – parameters− Name− Default− Type− Mandatory− ValueFromPipeline− ParameterSetName− Validation
− ValidateSet− ValidateScript
− switch
param (
)
param (
$Value
)
param (
$Value = 'The default value'
)
param (
[string]$Value
)
param (
[Parameter(Mandatory = $true)]
[string]$Value
)
param (
[Parameter(ValueFromPipeline = $true)]
[string[]]$Value
)
param (
[Parameter(ParameterSetName = ‘ByValue')]
[string]$Value,
[Parameter(ParameterSetName = 'ByCount')]
[int]$Count
)
. .\Script.ps1 -Value 'foo'
. .\Script.ps1 –Count 42
param (
[ValidateSet('High', 'Low')] [string]$Value
)
param (
[ValidateScript({ Test-Path -Path $_ -PathType Leaf
})]
[string]$Path
)
param (
[switch]$Force
)
if ($Force) {
}
if ($Force.IsPresent) {
}
. .\Script.ps1 –Force True
. .\Script.ps1 False . .\Script.ps1 –Force:$false
False
param (
[bool]$Force
)
if ($Force) {
}
. .\Script.ps1 –Force $true
True
. .\Script.ps1 –Force $falseFalse
> Scripts – output− return− Write-Output− Write-Host− Write-Verbose
− CmdletBinding− -Verbose
return 'The result'
The result
Write-Output 'The result'
The result
Write-Output 'The result'
Write-Output ‘More result'
The result
More result
Write-Host 'Message‘
Write-Host 'Message' -ForegroundColor Yellow
Write-Host 'Message' -BackgroundColor Magenta ` -ForegroundColor White
Write-Host ('Message {0}' -f 42)
[CmdletBinding()]
param (
)
Write-Verbose 'Verbose message‘
> Scripts – output− Write-Verbose -Verbose $VerbosePreference− Write-Debug -Debug $DebugPreference− Write-Warning -WarningAction $WarningPreference− Write-Error -ErrorAction $ErrorActionPreference− Write-Information -InformationAction $InformationPreference
− Action/Preference− SilentlyContinue− Continue− Stop
> Scripts – lifecycle
param (
)
# script-body here
. .\Script.ps1 -Value '1','2'
'1','2' | . .\Script.ps1
− $Value = '1','2'
− $Value = '2'
param (
[string[]]$Value
)
# script-body here
param (
[Parameter(ValueFromPipeline = $true)]
[string[]]$Value
)
# script-body here
$Value
> Scripts – lifecycleparam (
)
begin {}
process { # script-body here}
end {}
. .\Script.ps1 -Value '1','2'
'1','2' | . .\Script.ps1
− Begin− Process ($Value = '1','2')− End
− Begin− Process ($Value = '1')− Process ($Value = '2')− End
param (
)
begin {}
process { # script-body here}
end {}
param (
[string[]]$Value
)
begin {}
process { # script-body here}
end {}
param (
[Parameter(ValueFromPipeline = $true)]
[string[]]$Value
)
begin {}
process { # script-body here
$Value }
end {}
Show-Code
> Functionsfunction Verb-PrefixNoun {
}
function Verb-PrefixNoun {
param (
[string]$Value
)
# function-body here
$Value
}
function Verb-PrefixNoun { param (
[string[]]$Value
)
begin { }
process { # script-body here
$Value }
end { }}
> Modules− PowerShell Script or C#− C#
− System.Management.Automation namespace− Cmdlet base-class− Cmdlet attribute
− PowerShell Script− Collection of functions− .psm1− .psd1
> Modules−Import-Module−.psm1−.psm1 + .psd1
− New-ModuleManifest− Update-ModuleManifest
− Test-ModuleManifest−Script-files
function Get-SomeStuff {}
function Update-SomeStuff {}
function Remove-SomeStuff {}
@{
Author = 'Jeroen Swart'
RootModule = 'MyModule.psm1'
ModuleVersion = '1.0.0.0'
GUID = 'bbd0a9d3-8308-4e5b-9762-1cbc057dd1c4'
Description = '...'
PowerShellVersion = '4.0'
FunctionsToExport = (
'Get-SomeStuff',
'Update-SomeStuff',
'Remove-SomeStuff')
}
Get-ChildItem ` -Path "$PSScriptRoot\Internal" ` -Filter '*.ps1' |% { . $_.FullName }
Get-ChildItem ` -Path "$PSScriptRoot\Functions" ` -Filter '*.ps1' |% { . $_.FullName }
> Modules−Import-Module –Path '...'−Import-Module –Name '...'
− System− %windir%\System32\WindowsPowerShell\v1.0\
Modules− $pshome\Modules
− All users− %ProgramFiles%\WindowsPowerShell\Modules− "$($env:ProgramFiles)\WindowsPowerShell\
Modules"− Current user
− %UserProfile%\Documents\WindowsPowerShell\Modules
− $home\Documents\WindowsPowerShell\Modules
> Modules−Get-Module−Get-Module –ListAvailable−Remove-Module
−Import-Module –Force
• NuGet• Chocolatey• PowerShell Package Management• TFS Build• TFS Release Management• Remote PowerShell• PowerShell DSC• Server Management
> Select PowerShell | More
• NuGet• Chocolatey• PowerShell Package Management
> Select PowerShell | More
> NuGet−zip, maar .nupkg−lib
− net45− net40− portable-win+net45+wp8+win8+wpa81
−content−tools
− init.ps1− .psm1
−nuspec
> NuGet−init.ps1
−installPath−toolPath−package−project
− EnvDTE.Project− ProjectItems− DTE EnvDTE.DTE
> NuGet−Add/modify files & content in a project
−Build and/or run the solution−Code generation
− Entity Framework Migrations−Manage windows & documents−Enhance Visual Studio UI
Show-Code
> Chocolatey−Windows Package Manager
− choco list− choco install
−NuGet-based−nuspec−tools
− chocolateyInstall.ps1− chocolateyUninstall.ps1
> Chocolatey−Install-ChocolateyPackage−Install-ChocolateyZipPackage−Install-ChocolateyVsixPackage−Install-ChocolateyEnvironmentVariable−Install-ChocolateyFileAssociation
> Chocolatey
Install-ChocolateyPackage ` 'notepadplusplus' ` 'exe' ` '/S' ` 'https://notepad-plus-plus.org/repository/6.x/6.8.8/npp.6.8.8.Installer.exe'
Notepadplusplus (chocolateyInstall.ps1)
$packageName = 'GoogleChrome'
$app = Get-WmiObject -Class Win32_Product | Where-Object {$_.Name -eq 'Google Chrome'}if ($app) { $msiArgs = $('/x' + $app.IdentifyingNumber + ' /q REBOOT=ReallySuppress') Start-ChocolateyProcessAsAdmin $msiArgs 'msiexec'}
GoogleChrome (chocolateyUninstall.ps1)
> PowerShell Modules−xcopy
− System, All users, Current user
−Chocolatey package− xcopy
−PowerShell Package Management− PowerShell v5
> PowerShell Package Management−Package Manager Manager
> PowerShell Package Management−Module−Script−Package
−Find, Install, Update, Publish, Save−Find-Module−Install-Package
Show-Code
• TFS Build• TFS Release Management
> Select PowerShell | More
> TFS Build−XAML Build
−Task-based build− Script (in VC)− Arguments
> TFS Release Management−XAML
−Task-based− TFS 2015 Update 2
> TFS Release Management−Remote PowerShell
−PowerShell Scripts
−PowerShell Modules
−PowerShell DSC
−PowerShell Package Management
(Chocolatey)
> TFS Release Management
Build Drop-location
RM
Target-servers
Trigger release Execute script
Copy files to servers
> TFS Release Management
Build Package Source
RM
Target-servers
Chocolatey PackagesPowerShell Modules
Trigger release
Retrieve packages
Install packages
• Remote PowerShell• PowerShell DSC• Server Management
> Select PowerShell | More
> Remote PowerShell−Enter-PSSession & Exit-PSSession
−New-PSSession & Remove-PSSession−Invoke-Command -Session
> Remote PowerShell−Enable remoting
− Enable-PSRemoting−Check configuration
− Test-WSMan−Limit access
− Set-Item `wsman:\localhost\client\trustedhosts
[name] `-Concatenate-Force
> Remote PowerShell−'Double Hop'−CredSSP & Credential
−Server− Enable-WSManCredSSP -Role Server
−Client− Enable-WSManCredSSP -Role Client `
–DelegateComputer [machinename]
> PowerShell DSC
$server = new-Object Microsoft.SqlServer.Management.Smo.Server("(local)")if($Credential) { $server.ConnectionContext.Login = $Credential.UserName $server.ConnectionContext.SecurePassword = $credential.Password}
$database = $server.Databases |? { $_.Name -eq $Name }if (-not $database) { $database = New-Object Microsoft.SqlServer.Management.Smo.Database($server, $Name) $database.Create()}
PowerShell Script
> PowerShell DSC
bSqlDatabase Database { Ensure = "Present" Name = $DatabaseName}
PowerShell DSC
> PowerShell DSC− Desired State Configuration− Declarative
− Configuration− Resource
− Get− Test− Set
> PowerShell DSC− Push vs Pull
Show-Code
> Server Management−Server
− Processes− Services− Resources (RAM, CPU, …)
−IIS− Websites− App pools
− Logging
• notes in ppt• MSDN
• Windows PowerShell• PowerShell DSC• PowerShell SDK
• Blogs• Windows PowerShell Blog• Hey Scripting Guy• ...
• Books• Windows PowerShell in Action• Windows PowerShell Cookbook• Windows PowerShell for Developers• ...
> Get-Help
• PowerShell Workflow• Debugging (incl. remote)• Classes• ISE• Automation• Extensions/Add-ons• Unit testing (Pester)• Azure (incl. PowerShell DSC)
• OSS Packages & Modules
> _
?VRAGEN