Table of Contents
· Working with the script editor
o Assigning data to a variable
o Assigning data to variables – continued
· Looping
· Pipeline
Working with the script editor
You can use the out-of-the-box editor (Powershell ISE), or download and install PowerGUI. Both will give you code markup (coloring, auto-suggestions, etc) and the ability to run code within the same window.
Powershell File Types
· MyScript.ps1 – This is the default Powershell script extension
· There are other file types, but 99% of the scripts you write will be .ps1 files
Code Comments
You can write comments inside your script a few different ways.
001
002 |
# Script comments
$MyVariable = “Hello World!” |
Use the hash symbol “#” to comment out a line, shown in green above.
001
002 003 004 005 006 007 |
<#
Lots of code comments here. #> $MyVariable = “Hello World!” |
You can also comment out multiple lines using “<#” and “#>”, shown in green above.
Variables
Variables are declared with “$” at the beginning of the variable name and assigned a value with one equals sign “=”:
001
|
$MyVariable = “Hello World!”
|
A variable is just a container for data. It can be a string (“Hello World!”), a numeric value (100), or other types of data such as Powershell Objects or arrays.
Assigning data to a variable
· Assigning string data (enclose the string in quotes): $MyVariable = “Hello World!”
· Assigning numeric data: $MyVariable = 100
· Assigning data to an array:
001
002 003 004 005 |
$MyVariable = @()
$MyVariable += “Value1” $MyVariable += “Value2” Write-Host $MyVariable |
o Above, you declare the variable to be an array by assigning a value of “@()”. This converts the variable to an array and allows you to start adding data to the array. You don’t have to do this, but it’s a best practice to declare your variable types before adding data to it. Powershell isn’t as strict as other coding languages, so you don’t have to declare a variable to be a string/decimal/etc before assigning data to it.
o The second line in the above code is adding a value to the array by using “+=”. You can add data to the array in other ways as well. The last line in the code above will output the contents of the array to the screen.
Running Scripts
· To run the above script inside a script editor, copy the contents of the code into the code editor (Powershell ISE or PowerGUI) and press F5 or hit the green arrow button
· To run the above script in a PowerCLI window, save the script as a “ps1” file. Then run this command within the PowerCLI window:
· Above, the script name is “wip7”. Use “.\” before the name of the script to run the script within the PowerCLI window
· To run scripts like this, you need to “cd” into the same directory where you saved the script. So above you would need to run “cd H:\Documents\PowerCLI” to change directory first, and then run “.\wip7.ps1”
Running Scripts – continued
Powershell has an extremely useful feature called “Tab Completion”. If you type the partial name of a cmdlet and then press the Tab key, it will try to autocomplete the name of the cmdlet for you.
Assigning data to variables – continued
You can assign variables to other variables:
001
002 |
$MyVariable = “Hello World!”
$MyVariable2 = $MyVariable |
Assigning additional data to variables:
001
002 003 |
$MyVariable = “Hello World!”
$MyVariable2 = $MyVariable $MyVariable2 = $MyVariable2 + ” Powershell Knowledge Transfer” |
MyVariable2 started out as the string “Hello World!”, and then had another string added to it using the “+” operator.
If-Else Statements
Once you have gathered some data, you will want to run checks on the data to manipulate it.
The basic format of “If” statements are as follows:
If(Condition) {
Do something if the condition is met
}
Copy this code:
001
002 003 004 005 |
$MyVariable = 100
If($MyVariable -eq 100) { |
Above, we assign the numeric value “100” to MyVariable, and then run an “If” check to test the data we assigned. The “-eq” statement is checking if something is –equal or not. A full list of comparison operators is here.
“If” statements can be chained together like this:
If(Condition) {
Do something if this condition is met
}
ElseIf(Condition) {
Do something if this condition is met
}
Else {
Do something if none of the other conditions are met
}
An example of this is below:
001
002 003 004 005 006 007 008 009 010 011 012 013 |
$MyVariable = 200
If($MyVariable -eq 100) { ElseIf($MyVariable -eq 200) { Else { |
Looping
There are lots of ways to loop through data. Let’s build on the previous array example:
001
002 003 004 005 006 007 |
$MyVariable = @()
$MyVariable += “Value1” $MyVariable += “Value2” ForEach($obj in $MyVariable) { |
Above, we created the array and assigned data to it. Then we used a “ForEach” loop to step through each piece of data within the array, and then output the result every step of the way. “$obj” is a variable that we created to store the contents of each element in the array. The value of “$obj” will change after each time it loops – “$obj” will have “Value1” stored within it on the first loop, then “Value2” on the second loop.
Let’s combine a loop with an “If-Else” chain:
001
002 003 004 005 006 007 008 009 010 011 012 013 |
$MyVariable = @()
$MyVariable += “Value1” $MyVariable += “Value2” ForEach($obj in $MyVariable) { ElseIf($MyVariable -eq “Value2”) { |
This will loop through every element in the “$MyVariable” array, and run checks on the data stored within “$obj”. Notice that we don’t need an “Else” statement – this is optional.
Getting Help
Scripts (aka “cmdlets”) will most likely have built-in help that you can use. Run this command to get help on the “Write-Host” cmdlet:
001
|
Get-Help Write-Host –Full
|
Pipeline
The pipeline is comparable to water pipes that run through a home. Each water pipe is separate from each other, but they are also linked together to form a chain. The water flowing through the pipeline is the data that you send through it. A brief explanation of the pipeline is here.
There are a variety of ways to manipulate data in the pipeline:
1. Out-Gridview , Out-Null
2. ForEach-Object
3. Where-Object
Out-GridView, Out-Null
Out-GridView will redirect the output from your command to a new window that has sortable columns. You can copy and paste from the Out-GridView window.
001
|
Get-Process -Name “explorer” | Out-GridView
|
Out-Null is sort of like a “catch all” cmdlet that will suppress the output from the command you run. The unsuppressed command looks like this:
With suppression:
ForEach-Object
A great explanation of ForEach-Object is here.
Where-Object
“Where-Object” is a way to filter out data in the pipeline. Take the original code example above:
001
|
Get-Process -Name “explorer” | Out-GridView
|
Instead of writing the code like that, you could use “Where-Object” to filter out the data instead (this isn’t efficient, but useful for our learning purposes):
001
|
Get-Process | Where-Object {$_.Name -eq “explorer”} | Out-GridView
|
“Where-Object” takes data that is sent to it from another cmdlet (shown as “Get-Process” above) and then filters out the data based on the checks you run against it. Above, the check to run follows this format:
Cmdlet | Where-Object {$_.ObjectName –ComparisonOperator ConditionToMatchOn}
The “$_” section of code is the current object in the pipeline to run checks against. In the example above, we are checking the “Name” property to see if it equals the name “explorer”. If you didn’t know the name of the property you want to match on, you would start out by examining the “Get-Process” object (remember, it’s just a big box full of data that you can explore):
001
|
Get-Process | Get-Member
|
So we see above that the “Get-Process” object has a smaller object named “ProcessName” which we can use to filter out data with “Where-Object”.
It’s important to note that the pipeline works by sending one object at a time to the next cmdlet in the chain:
001
|
Get-Process | Where-Object {$_.Name -eq “explorer”} | Out-GridView
|
Above, the first object that “Get-Process” retrieves would be sent to “Where-Object”:
Above, the “ApMsgFwd” object would be sent through the pipeline first, and then “AptEx”, etc. Each “ProcessName” is an object, which is why you reference the objects with “$_.Name”. The “$_.” section in the preceding code basically means to take the current object in the pipeline, and reference the “Name” property within the object (“$_.Name”). Another way to visualize this in action is to view it like this (this is an abstract example):
001
|
Get-Process | Where-Object {CurrentPipelineObject.Name -eq “explorer”} | Out-GridView
|
VMware Examples
VMware created a series of scripts and packaged it into a snap-in. To load the snap-in within a script, use this code:
001
|
Add-PSSnapin VMware.VimAutomation.Core
|
PowerCLI sits “on top” of Powershell. PowerCLI is a customized Powershell window that automatically loads the above snap-in.
To connect to a vCenter server and begin running commands, use this code:
001
|
Connect-VIServer “vCenterServerName”
|
Some initial cmdlets to get familiar with that VMware created:
001
002 003 004 |
Get-VM
Get-VMHost Get-Cluster Get-Datacenter |
Each of these can accept different parameters. For example:
001
|
Get-VM -Name “lappmab00035009”
|
Everything in Powershell is an object. Think of an object as a box. This box can contain other boxes (other objects), and it can also have tools (object methods) within the box to manipulate data. To open up the box and view its data, you can use the “Get-Member” cmdlet:
001
|
Get-VM -Name “lappmab00035009” | Get-Member
|
The output from this command will display everything within the object you retrieved:
Above, there are some tools you can work with (Methods), and also “Properties”. Properties are just collections of data – other, smaller boxes within the larger box.
First, we retrieve the data with “Get-VM”. Then we use the pipe command “|” to send the larger object into the pipeline. Once the object is in the pipeline, we can manipulate and filter the data. We decided to use the “Select-Object” cmdlet to pick out only one smaller object to view:
001
|
Get-VM -Name “lappmab00035009” | Select-Object Name
|
So above, there is a single column “Name” that contains the “lappmab00035009” piece of data. This result is still an object – let’s view the contents of this smaller object:
001
|
Get-VM -Name “lappmab00035009” | Select-Object Name | Get-Member
|
There is much less going on inside this object. Notice the “NoteProperty” section of the “MemberType” column. Within this object there is a piece of data we can retrieve:
001
|
Get-VM -Name “lappmab00035009” | Select-Object -ExpandProperty Name
|
Above, we are using the “Select-Object” parameter “-ExpandProperty” to pull out the “Name” property within the object.
So let’s tie it all together with a script:
001
002 003 004 005 006 007 008 009 010 011 012 013 |
Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer “wmgtmab00001012” $MyVariable = @() ForEach($obj in $MyVariable) { |
The script does the following:
1. Adds the VMware snap-in (not necessary if you run the script from a PowerCLI window)
2. Connects to the vCenter server
3. Retrieves two “Get-VM” objects and stores the objects into the $VM1 and $VM2 variables
4. Creates an array $MyVariable
5. Assigns the $VM1 and $VM2 objects as elements of the array (elements are like individual cells of data within Excel)
6. Loops through the array and outputs the “Name” property within each object stored in the array
Piping vs. Dot-Notation
Instead of using the “|” (pipe) operator, you can use dot-notation to reference values within an object. Dot-notation looks like this:
001
002 003 004 005 006 007 008 009 010 011 012 013 014 |
Add-PSSnapin VMware.VimAutomation.Core
Connect-VIServer “wmgtmab00001012” $VM1 = Get-VM -Name “lappmab00035009” $MyVariable = @() ForEach($obj in $MyVariable) { |
Above, we referenced the “Name” Property using dot-notation. Compare this code with what was shown in the original example.
Code Format
It is a best practice to indent your code and use code comments. See below.
001
002 003 004 005 006 007 008 009 010 011 012 013 014 015 |
<#
Below is a block of code that performs some function. The script comments are above the block of code to increase readability without breaking up the “flow” of the code. #> ForEach($obj in $MyCollection) { If($Something -eq $SomethingElse) { Write-Host “Properly indented code is wonderful!” } # End “If($Something -eq $SomethingElse)” } # End “ForEach($obj in $MyCollection)” |