Saturday, December 21, 2013

Learning PowerShell

$PSVersionTable

PowerShell v3 has two components: the standard, text-based console host (Power-

Shell.exe) and the more visual Integrated Scripting Environment (ISE; PowerShell_ISE.exe)

Add-WindowsFeature powershell-ise


$PSVersionTable


you can run PowerShell.exe -version 2.0 to explicitly run v2. 


PowerGUI

PowerSE and PowerWF
Idera PowerShell Plus

help Get-Service

update-help

Help *log*

Help *event*
get-alias -Definition "Get-Service"

A cmdlet is a native PowerShell command-line utility.

Taking shortcuts
Truncating parameter names
PowerShell doesn’t force you to type out entire parameter names
Parameter name aliases

Positional parameters


Get-ChildItem c:\users

move -Path c:\file.txt -Destination \users\donjones\

Show-Command Get-EventLog


Working with providers


Get-PSProvider

A PowerShell provider, or PSProvider, is an adapter. It’s designed to take some kind
of data storage and make it look like a disk drive.

A PSDrive uses a single provider to connect to some actual data storage.

Get-PSDrive

The PSProvider adapts the data

store, the PSDrive makes it accessible, and you use a set of cmdlets to see and manipulate
the data exposed by each PSDrive.

get-command -noun *item*


Set-Location -Path C:\Windows

cd 'C:\Program Files'
new-item testFolder
Type: directory

mkdir test2

-Type Directory

PowerShell’s solution is to provide an alternate -LiteralPath parameter. This

parameter doesn’t accept wildcards.

set-location -Path hkcu:

set-location -Path software
get-childitem
Set-ItemProperty -Path dwm -PSPropert EnableAeroPeek -Value 0

The pipeline: connecting commands

Dir | More

Exporting to a CSV or an XML file

Get-Process (or Ps)
Get-Service (or Gsv)
Get-EventLog Security -newest 100


Get-Process | Export-CSV procs.csv


Export-CliXML | Import-CliXML

Import-CSV
Get-Command -verb Import or Export

Comparing files: Compare-Object | Diff

-ReferenceObject, -DifferenceObject, and -Property

Get-Process | Export-CliXML reference.xml

Diff -reference (Import-CliXML reference.xml) -difference (Get-Process) -property Name

The parameter names are -referenceObject and -differenceObject;


Dir > DirectoryList.txt

Dir | Out-File DirectoryList.txt
PowerShell has a variety of Out- cmdlets. One is called Out-Default, and it’s the one
the shell uses when you don’t specify a different Out- cmdlet

Get-Command Out*

Get-Command -verb Out

Out-Printer

ut-GridView
Get-Service | Out-GridView
Out-Null and Out-String
Get-Service | ConvertTo-HTML

Get-Service | ConvertTo-HTML | Out-File services.html

ConvertTo-CSV and ConvertTo-XML
Export-CSV or Export-CliXML

Get-Process | Stop-Process

Get-Process -name Notepad | Stop-Process
Get-Service can be piped to cmdlets
like Stop-Service, Start-Service, Set-Service

all

cmdlets that modify the system have an internally defined impact level. The cmdlet’s
creator sets this impact level and it can’t be changed. The shell has a corresponding
$ConfirmPreference setting, which is set to High by default.

$confirmpreference

Get-Service | Stop-Service -confirm

-whatif

get-process | stop-process -whatif
This tells you what the cmdlet would have done, without letting the cmdlet do it.

Get-Content .\events.csv

import-csv .\events.csv
The Import- cmdlets pay attention to what’s in the file, attempt
to interpret it, and create a display that looks more like the output of the original
command (Get-EventLog, in this case).

Microsoft Management Console (MMC)




Discovering objects: Get-Member

To learn more about an object, you use a different
command: Get-Member.
Get-Process | Gm

? ScriptProperty

? Property
? NoteProperty
? AliasProperty
Get-Process -Name Notepad | Stop-Process
Stop-Process -name Notepad

Get-Process | Sort-Object -property VM

-descending
Get-Process | Sort VM -desc
Get-Process | Sort VM,ID -desc

Selecting the properties you want: Select-Object

Get-Process | Select-Object -property Name,ID,VM,PM | Convert-ToHTML | Out-File test2.html
Select-Object is used to choose the properties (or columns) you want to
see. Where-Object removes, or filters, objects out of the pipeline
based on some criteria you specify.
PSObjects

Get-Process | Sort VM -descending | Select Name,ID,VM | gm


Get-Content .\computers.txt | Get-Service


pipeline parameter binding:

The first method the
shell will try is called ByValue; if that doesn’t work, it’ll try ByPropertyName.

pipeline input ByValue

For the most part, commands sharing the
same noun (as Get-Process and Stop-Process do) can usually pipe to each other
ByValue.

pipeline input ByPropertyName

import-csv .\aliases.csv | new-alias

custom properties

import-csv .\newusers.csv |
select-object -property *, @{name='samAccountName';expression={$_.login}},
@{label='Name';expression={$_.login}}, @{n='Department';e={$_.Dept}}

Parenthetical commands

Get-WmiObject -class Win32_BIOS -ComputerName (Get-Content .\computers.txt)

Extracting the value from a single property

get-adcomputer -filter * -searchbase "ou=domain controllers, dc=company,dc=pri"

Select-Object cmdlet includes an

-expandProperty parameter, which accepts a property name. It will take that property,
extract its values, and return those values as the output of Select-Object.

-Expand Name goes into the Name

property and extracts its values, resulting in simple strings being returned
from the command.
Get-Service -computerName (get-adcomputer -filter * -searchbase "ou=domain controllers,dc=company,dc=pri" | Select-Object -expand name)

Select-Object and its -Property parameter: it doesn’t change the

fact that you’re outputting an entire object.

Get-Process -computerName (import-csv .\computers.csv | select -expand hostname)


With Select -Property, you’re deciding

what boxes you want, but you’ve still got boxes. With Select -ExpandProperty,
you’re extracting the contents of the box, and getting rid of the box entirely. You’re
left with the contents.

About the default formatting

.format.ps1xml files that install with PowerShell.
formatting directions for process objects are in DotNetTypes.format.
ps1xml.

cd $pshome

notepad dotnettypes.format.ps1xml

Filtering and comparisons

early filtering
Get-Service -name e*,*s*
Get-ADComputer -filter "Name -like '*DC'"

Filter left

Where-Object| Where uses a generic syntax, and you can use it to filter any kind of object once you’ve
retrieved it and put it into the pipeline.

Comparison operators: -eq, -ne, -ge, -le, -gt, -lt

For string comparisons, you can also use a separate set of case-sensitive operators if
needed: -ceq, -cne, -cgt, -clt, -cge, -cle.
-not -and, -or
-like, -notlike, use -clike and -cnotlike for case-sensitive comparisons.
-match makes a comparison between a string of text and a regular expression
pattern. -notmatch is its logical opposite, and as you might expect, -cmatch and
-cnotmatch provide case-sensitive versions.

Filtering objects out of the pipeline

Get-Service | Where-Object -filter { $_.Status -eq 'Running' }

Get-WmiObject -Class Win32_Service |

Where { $_.State -ne 'Running' -and $_.StartMode -eq 'Auto'}

Power-

Shell Iterative Command-Line Model, or PSICLM
Get-Process | Where-Object -filter { $_.Name -notlike 'powershell*' } |
Sort VM -descending | Select -first 10 |
Measure-Object -property VM -sum

Register-ScheduledTask -TaskName "ResetAccountingPrinter" -Descript

ion "Resets the Accounting print queue at 3am daily" -Action (New-Scheduled
TaskAction -Execute 'Get-PrintJob -printer "Accounting"') -Trigger (New-Sch
eduledTaskTrigger -daily -at '3:00 am')

Remote control: one to one, and one to many

PowerShell uses a new communications protocol called Web Services
for Management (WS-MAN).

Multitasking with background jobs

start-job -scriptblock { dir }
start-job -scriptblock {
get-eventlog security -computer server-r2
}

Get-History 32 -count 32


PowerShell: Sending Http Request
Invoke-WebRequest
http://technet.microsoft.com/en-us/library/hh849901.aspx
$r = Invoke-WebRequest -URI http://www.bing.com?q=how+many+feet+in+a+mile
$r.AllElements | where {$.innerhtml -like "*=*"} | Sort { $.InnerHtml.Length } | Select InnerText -First 5

PowerShell: Executing a .NET Web Request
http://blog.newslacker.net/2012/03/powershell-executing-net-web-request.html
# // first argument is mapped to $url

$url="http://localhost:8983/solr/select?fl=contentid&q=contentid"
param($url)

# // create a request
[Net.HttpWebRequest] $req = [Net.WebRequest]::create($url)
$req.Method = "GET"
$req.Timeout = 600000 # = 10 minutes

# // Set if you need a username/password to access the resource
#$req.Credentials = New-Object Net.NetworkCredential("username", "password");

[Net.HttpWebResponse] $result = $req.GetResponse()
[IO.Stream] $stream = $result.GetResponseStream()
[IO.StreamReader] $reader = New-Object IO.StreamReader($stream)
[string] $output = $reader.readToEnd()
$stream.flush()
$stream.close()

# // return the text of the web page
Write-Host $output

http://www.powershellpro.com/powershell-tutorial-introduction/variables-arrays-hashes/
$_ – 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.

http://ss64.com/ps/syntax-arrays.html
$myArray = 1,"Hello",3.5,"World"
or using explicit syntax:
$myArray = @(1,"Hello",3.5,"World")
$myArray = (1..7)

or strongly typed:
[int[]] $myArray = 12,64,8,64,12
Create an empty array:
$myArray = @()
Create an array with a single element:
$myArray = @("Hello World")
Create a Multi-dimensional array:
$myMultiArray = @((1,2,3),(40,50,60))
Add values to an Array.
$monthly_sales += 25
$myArray[0]
$myArray
$myArray[4..9]
$myArray[-1]
$myArray.length-1
foreach ($element in $myArray) {$element}

ow can I use Windows PowerShell to check a string to see if it contains another string?
PS C:\> $a = [string]"This string contains a number of letters"
PS C:\> $a -match 'a number'
$index = "The string".IndexOf(" ")

http://ss64.com/ps/syntax-compare.html
-eq             Equal
 -ne             Not equal
 -ge             Greater than or equal
 -gt             Greater than
 -lt             Less than
 -le             Less than or equal
 -like           Wildcard comparison
 -notlike        Wildcard comparison
 -match          Regular expression comparison
 -notmatch       Regular expression comparison
 -replace        Replace operator
 -contains       Containment operator

 -notcontains    Containment operator

Running Scripts Without Starting Windows PowerShell
powershell.exe -noexit &'c:\my scripts\test.ps1'
powershell.exe -noexit get-childitem c:\scripts
Set objShell = CreateObject("Wscript.Shell")
objShell.Run("powershell.exe -noexit c:\scripts\test.ps1")

Run a PowerShell script
http://ss64.com/ps/syntax-run.html
The most common (default) way to run a script is by calling it:
PS C:\> & "C:\Belfry\My first Script.ps1"
If the path does not contain any spaces, then you can omit the quotes and the '&' operator
PS C:\> C:\Belfry\Myscript.ps1
If the script is in the current directory, you must indicate this using .\ (or ./ will also work)
PS C:\> .\Myscript.ps1
Dot Sourcing
When you dot source a script, all variables and functions defined in the script will persist even when the script ends.
Run a script by dot-sourcing it:
PS C:\> . "C:\Belfry\My first Script.ps1"

http://www.joynt.co.uk/kb/scripting/powershell/stopwatch
$elapsed = [System.Diagnostics.Stopwatch]::StartNew()
write-host "Total Elapsed Time: $($elapsed.Elapsed.ToString())"

http://technet.microsoft.com/en-us/magazine/jj554301.aspx
Param(
  [string]$computerName,
  [string]$filePath
)
[CmdletBinding()]
Param(
  [Parameter(Mandatory=$True,Position=1)]
   [string]$computerName,

   [Parameter(Mandatory=$True)]
   [string]$filePath
)
param([String[]] $Hosts, [String] $VLAN)

Get-Content one.sql,two.sql,three.sql,four.sql,five.sql > master.sql
Get-Content [-Path] <String[]> [-Credential <PSCredential> ] [-Exclude <String[]> ] [-Filter <String> ] [-Force] [-Include <String[]> ] [-ReadCount <Int64> ] [-Tail <Int32> ] [-TotalCount <Int64> ] [-UseTransaction] [ <CommonParameters>]

A foreach loop doesn't ouput to the pipeline. You can make it do that by making the loop a sub-expression:

Check file existence
if(!(Test-Path -Path $path))
If(-not(Test-Path -Path $path))

http://poshoholic.com/2007/08/21/essential-powershell-understanding-foreach/
The foreach statement does not use pipelining.  Instead, the right-hand side of the in operator is evaluated to completion before anything else is done.  For our example above, the Get-Command cmdlet is called and the results are completely loaded into memory before the interior script block is executed.  This means you have to have enough memory to store all of the objects when you run the script. 
In contrast, the foreach alias, or ForEach-Object cmdlet, does use pipelining.  When the second example is used, Get-Command is called and it starts to return the commands one at a time.  As each object is returned out of the Get-Command cmdlet, it is sent into the pipeline and execution continues in the next section of the pipeline.  In this case, the foreach alias gets executed and the object is run through the process script block of ForEach-Object.

http://blogs.technet.com/b/gbordier/archive/2009/05/05/powershell-and-writing-files-how-fast-can-you-write-to-a-file.aspx
use the ‘>>’' alias that calls into the out-file cmd-let
use export-csv
use .Net
use .Net StreamWriter to write the file
$stream = [System.IO.StreamWriter] "t.txt"
1..10000 | % {
      $stream.WriteLine($s)
}
$stream.close()

You can expand ..\frag to its full path with resolve-path:
PS > resolve-path ..\frag 
[IO.Path]::GetFullPath( "fred\frog\..\frag" )
or more interestingly
[IO.Path]::GetFullPath( (join-path "fred\frog" "..\frag") )

PowerShell has really wacky return semantics - at least when viewed from a more traditional programming perspective. There are two main ideas to wrap your head around:

All output is captured, and returned
The return keyword really just indicates a logical exit point
Thus, the following two script blocks will do effectively the exact same thing:

$a = "Hello, World"
return $a
$a = "Hello, World"
$a
return

The $a variable in the second example is left as output on the pipeline and, as mentioned, all output is returned. In fact, in the second example you could omit the return entirely and you would get the same behavior (the return would be implied as the function naturally completes and exits).

Write-Host is typically the only one I frequently use—in particular with its NoNewLine switch. What NoNewLine provides is a simple way to join different lines together.
Write-Host –NoNewLine "Counting from 1 to 9 (in seconds):  "
foreach($element in 1..9){
  Write-Host –NoNewLine  "${element} "
  Start-Sleep –Seconds 1
}
Write-Host ""
Something else that Write-Host is useful for is when one might want to add color in their output. 
Write-Host –NoNewLine  "${element} " -BackgroundColor "Red" -ForegroundColor "Black"
In Windows PowerShell, the host is what you, as a user, interact with.

Write-Host: Write directly to the console, not included in function/cmdlet output. Allows foreground and background colour to be set.
Write-Debug: Write directly to the console, if $DebugPreference set to Continue or Stop.

Write-Verbose: Write directly to the console, if $VerbosePreference set to Continue or Stop.

No comments:

Post a Comment