<#
____ ____ _ _ _
| _ \ _____ _____ _ __/ ___|| |__ ___| | |
| |_) / _ \ \ /\ / / _ \ '__\___ \| '_ \ / _ \ | |
| __/ (_) \ V V / __/ | ___) | | | | __/ | |
|_| \___/ \_/\_/ \___|_| |____/|_| |_|\___|_|_|#>
# pay no attn to the below goop (this should help me track my progress during the talk)
$groupName = 'TODO Fill this in!!!'
. .\TimeTracker.ps1
Start-TrackingTime 65 # <-- how long is this talk?
<#
- Twitter: @staxmanade
- Blog: http://elegantcode.com
- Some Code: http://github.com/staxmanade
- Employer: Vertigo
J.A.S.O.N.
J - July
A - August
S - September
O - October
N - November#>
HowsMyTime "yourself"
<#- How many have ever used powershell?
- Programming experience:
- More than 10 years?
- Between 5-10 years?
- Between 3-5 years?
- Less than 3 years?
- Who has any amount of background in the Microsoft .Net space?
- First a little background and fluffy stuff
- Language intro/overview
- Runtime Environment intro/overview
- Tips/Tricks
- Fun Stuff
Windows PowerShell AKA (Windows Management Framework)
PowerShell is a dynamically typed scripting language composed of 2 major components
- Language
- Runtime environment
- Command.com or cmd.exe
- Monad Manifesto (August 2002)
- First demoed at (PDC 2003)
- V 1.0 (November 2006)
- V 2.0 (August 2009)
- V 3.0 (Last quarter of 2012)
- V2.0 comes pre-installed on systems >= Win7 and Server 2008 R2
- V2.0 can be installed on windows going all the way back to Windows XP
- OSS linux ports out there that run on top of the Mono framework
- Automate your daily mundane
- Prototype against .Net framework classes w/out having to
File -> New -> Console Project - If you know .net you are almost there
#>
HowsMyTime "powershell overview"
<## <--- to comment out a line
<#
Comment out a block of stuff
This whole presentation is littered with them :) !!!!
#>$v1 = 1
echo $v1
$v2 = $v1 + 1;
echo $v2
# explicitly define it's data type
[int] $num1 = 1
echo $num1
# Notice how the .2 gets rounded as it converts it to an integer
[int] $num2 = 1.2
echo $num2
[decimal] $num3 = 1.2
echo $num3$v3 = @( 1, 2, 3 )
echo $v3
# Working with Arrays
# Concat 2 arrays
@(1,2,3) + @('a', 'b', 'c') + @(4,5,6)
# Different ways to add to an array.
$a1 = @(1,2,3); $a1
$a1 += 4; $a1
$a1 += 5; $a1
$a1 += 6; $a1
$a1 += @(7,8,9); $a1
# Can't remove from the array. You'd have to create a new array with just the items you wanted. (Or use a .net class to do it list)
$a1 -= 7$v3 = @{
"name1" = "value1";
"name2" = "value2";
"name3" = "value3";
}$v3["name1"]
$v3.name1$v3.HelloKey = "Hello Value"
$v3["HelloKey"] = "Hello Something else"
$v3.HelloKey'Hello World!'
# or
"Hello World!"@'
Hello
World
'@Note - these won't work
@'Hello
World
'@
@'
Hello
World'@'Hello $groupName' "Hello $groupName""groupName variable is of type: $($groupName.GetType().FullName)"
"2 + 1564 = $(2 + 1564)"
"Current DateTime is = $(get-date)"
"Current DateTime is = $([System.DateTime]::Now)""Escape a quotation `"This is quoted`"."'Escape a quotation "This is quoted".'
"Escape a quotation `"$(get-date)`""
'Mix single and double quotes "$(get-date)".' # <-- notice the single quote - no interpolation 1 -eq 1 # equal
1 -ne 0 # not equal
1 -gt 0 # greater than
1 -ge 1 # greater than or equal
1 -lt 4 # less than
1 -le 1 # less than or equal
"something" -like "*ethin*" # Wildcard comparison
"something" -notlike "*gni*" # Wildcard comparison
"This $groupName is boring!" -replace 'boring', 'AWESOME' # Replace operator
@(1,2,3) -contains 1 # Containment operator
@(1,2,3) -notcontains 0 # Containment operator # EX: -eq becomes -ceq (Case sensitive equal to)
"aBc" -ceq "ABC" # (nope) "Welcome to the $groupName" -match "Welcome (.*)" # Regular expression comparison
$matches
"Welcome to the $groupName" -notmatch "Welcome (.*)" # Regular expression comparison
$matches !$true # Not $true
(-not $true) # Not $true
$true -and $true # And
$false -or $true # Orif( $true -or $false -or 1 -or "hi") {
$true
}$v1 = 'c'
if( $v1 ) {
"a"
} elseif( $v1 ) {
"b"
} elseif( $v1 ) {
"c"
} else {
"d"
}$v1 = 10
while( $v1 -gt 0 ) {
$v1--
echo $v1
}$v1 = 10
do {
$v1--
$v1
} while ( $v1 -gt 0 )for($i = 0; $i -lt 10; $i++) {
"$i"
}$files = ls
foreach($file in $files) {
"{0,10} bytes" -f $file.Length
}$v1 = "hi"
switch($v1) {
"hello" { "no" }
"world" { "no" }
"hi" { "yes" }
default { "no" }
}###try/catch/finally
try {
throw "Oh SNAP!"
} catch {
$_
}
finally{
"Do some Cleanup"
}# unlike *nix pipeline the output of the operation is not text but an object
ls | Get-Member
ls | where { $_.Extension -eq ".ps1" } | Sort-Object Length -Descending
$output = (ls | where { $_.Extension -eq ".ps1" } | Sort-Object Length -Descending)
$output.GetType()
$output[0].GetType()1..15
[char]'A'..[char]'z' | %{ [char]$_ }
1..15 | foreach{ "I can count to $_" }Get-ChildItem./HelloFromAScript.ps1function HelloFromAFunction()
{
echo "Hello World!"
}
HelloFromAFunction # Execute the above defined function
function OneParamApproach($param1, $param2)
{
echo "$param1 - $param2"
}
OneParamApproach "Placing the params within the parentheses is one approach"
# same as above example for 2 parameters
function AnotherParamApproach()
{
[param](
$param1,
$param2
)
echo "$param1 - $param2"
}
OneParamApproach "Placing the params within the parentheses is one approach"
# function that supports the pipeline.
function Add-Them-Up {
BEGIN {
# one time (at the beginning) setup code
$total = 0
}
PROCESS {
# grab the current item
$currentItem = $_
# do something with the item
$total += $currentItem
}
END {
# one time (at the end) teardown code
$total
}
}
@(1,2,3) | Add-Them-Up
1..100 | Add-Them-Up# already in your environment's "PATH"
ipconfig.exe
where.exe ipconfig
where.exe powershell
# by specifying full path
C:\Windows\System32\ipconfig.exe
# execute a command who's path was stored in a variable
$cmd = 'C:\Windows\System32\ipconfig.exe'
& $cmd /?
# same as above (without the variable)
C:\Windows\System32\ipconfig.exe /?# ctor of - DateTime(int year, int month, int day)
$JanFirst2009 = New-Object System.DateTime @(2009, 1, 1)
$JanFirst2009
$JanFirst2009.GetType()$JanFirst2009.AddDays(1)[System.DateTime]::Now[System.String]::Format("Hello {0}!", $groupName) $timer = New-Object Timers.Timer
$timer.Interval = 1000
$timer.Start()
$job = Register-ObjectEvent -inputObject $timer -eventName Elapsed `
-sourceIdentifier Timer.Random `
-Action { Get-Random -Min 0 -Max 100;}
Receive-Job $job
$timer.Stop();
Unregister-Event Timer.Random$someXml = [xml]'
<root>
<person id="1002854">
<firstName>Jason</firstName>
<lastName>Jarrett</lastName>
</person>
<person id="532486">
<firstName>Jesse</firstName>
<lastName>Anderson</lastName>
</person>
</root>'
$someXml
$someXml.GetType()
$someXml.root
$someXml.root.GetType()
$someXml.root.person[0]
$someXml.root.person[0].GetType()
$someXml.root.person[0].firstname
$someXml.root.person[0].firstname.GetType()
$someXml.root.person[0].id
foreach($person in $someXml.root.person){
$person.lastName
}
$someXml.root.person | where { $_.id -eq 1002854 }HowsMyTime "the powershell language"<# - Powershell Console (Built-in)
- Powershell ISE (Built-in)
- PowerGUI (3rd party)
- others? (probably)- Chocolatey
- cinst wincommandpaste
#> cd C:\
ls \\SomeNetworkShare\Folder\file.txtGet-PSDrive# Note this is not a system/wide change, but the current powershell environment
New-PSDrive -PSProvider filesystem -Root C:\Code\ -Name Codels variable: | measure
$someNewRandomVar = 1
ls variable: | measurePush-Location
#open regedit
regedit
cd HKCU:\
ls
cd HKCU:\Software
ls
# create a registry folder
mkdir JasonJ
cd .\JasonJ
Set-ItemProperty . newproperty "mynewvalue"
Pop-Location
rmdir HKCU:\Software\JasonJ -Force# - Sql Server
# - Active Directory
# - build your own?# Many of the commands you may know from dos or linux scripting work in PowerShell - accomplished by aliases
# (map commands to shortcuts)aliasalias dir
alias ls# alias foo to the Get-ChildItem cmdlet
set-alias foo Get-ChildItem
foo$Profile is a global variable that describes where the current environment can load a profile script
$Profile# 1. Create the directory
# 2. Create the file
# 3. Customize it for your own needs
# what is in the current profile?
cat $Profile
notepad $profile# Powershell Console
# Powershell ISE
# The NuGet Package Manager Console (inside Visual Studio) uses different pathGet-ExecutionPolicy
Set-ExecutionPolicy -ExecutionPolicy Restricted
<#
Restricted - No scripts can be run. Windows PowerShell can be used only in interactive mode.
AllSigned - Only scripts signed by a trusted publisher can be run.
RemoteSigned - Downloaded scripts must be signed by a trusted publisher before they can be run.
Unrestricted - No restrictions; all Windows PowerShell scripts can be run.
#>get-help about_CommonParameters
# WhatIf
mkdir temp
cd .\temp
1..10 | %{ new-item -Name "$_.txt" -type file }
rm *.txt -WhatIf
ls
rm *.txt
ls
# ErrorAction
rm This_file_doesnt_exist_on_disk.txt
rm This_file_doesnt_exist_on_disk.txt -ErrorAction silentlycontinueHowsMyTime "the powershell runtime environment". .\SomeExternalScript.ps1
# Now I can access functions/variables the external script contains# open windows explorer at the current directory
ii .
ii http://google.com # <-- I wish this worked - might write my own a wrapper?"Hello $groupName" | clip
cat README.md | clipGet-Help
Get-Help ls
Get-Help aliasShow-Command lsGet-HistoryStart-Process PowerShell -Verb RunAsBy default powershell does not stop executing a script on error. When developing build scripts set:
$ErrorActionPreference = "stop";msbuild.exe mySolution.sln
if($LASTEXITCODE -ne 0) { throw "build error" }ls | out-gridview([xml] (new-object net.webclient).downloadstring('http://feeds.feedburner.com/ElegantCode')) | %{ $_.rss.channel.Item } | select title, creator1..100 | foreach{
Write-Progress -activity "Sample progress bar" -PercentComplete $_;
sleep -Milliseconds 20
}1kb # ==> kilo-byte 1024
1mb # ==> mega-byte 1048576
1gb # ==> giga-byte 1073741824
1tb # ==> tera-byte 1099511627776
1pb # ==> peta-byte 11258999068426240 11,258,999,068,426,240
#1eb # ==> exa-byte ERR: does not work (but why would you need something that big?)
#1zb # ==> zetta-byte ERR: wat?
#1yb # ==> yotta-byte ERR: really?note you don't have to use 1*b (ex: 1kb) you can specify any number (213kb ==> 218112)
set-executionpolicy unrestricted;
iex ((new-object net.webclient).DownloadString('https://raw.github.com/staxmanade/DevMachineSetup/master/Bootstrap/BootIt.ps1'))
# Of particular interest
# - CD override
# http://elegantcode.com/2012/11/01/more-than-slightly-modified-cd-command-for-powershell/ HowsMyTime "so-called useful stuff"# http://elegantcode.com/2011/08/30/powershell-text-to-speech-and-fun-with-a-4yr-old/
# case internet is down
function Start-The-Fun()
{
$voice = new-object -com SAPI.SpVoice;
while($true)
{
write-host "->" -NoNewLine;
$msg = read-host;
$Voice.Speak( $msg, 1 ) | out-null;
}
}iex (New-Object Net.WebClient).DownloadString("http://bit.ly/e0Mw9w")HowsMyTime "done"<#
- Twitter: @staxmanade
- Blog: http://elegantcode.com
- Some Code: http://github.com/staxmanade
- Employer: Vertigo
____ ____ _ _ _
| _ \ _____ _____ _ __/ ___|| |__ ___| | |
| |_) / _ \ \ /\ / / _ \ '__\___ \| '_ \ / _ \ | |
| __/ (_) \ V V / __/ | ___) | | | | __/ | |
|_| \___/ \_/\_/ \___|_| |____/|_| |_|\___|_|_|
#>