PowerShell

PowerShell Basics
Introduction to PowerShell
Windows PowerShell is a Microsoft .NET Framework-connected environment designed for administrative automation. Windows PowerShell provides a new approach to building commands, composing solutions, and creating graphical user interface-based management tools.
Windows PowerShell enables a system administrator to automate the administration of system resources by the execution of commands either directly or through scripts.
The version of Windows used for this class is Windows Server 2012 R2.
PowerShell is a command line environment.
Why Use PowerShell?
- Preferred interface for managing Windows Server
- Low level access to system attributes and settings
- Allows scripting of operations against multiple servers
The PowerShell Interface
Windows PowerShell is a 64-bit application. Windows PowerShell (x86) is the 32-bit version of PowerShell.
Right clicking on the Windows PowerShell icon opens a context menu that allows you to execute Windows PowerShell with various options. For example, it is possible to execute PowerShell as an administrator to perform certain elevated tasks.
Windows Integrated Scripting Environment, or ISE, is a 64-bit application that is a GUI that allows for the development of scripts. Windows ISE (x86) is the 32-bit version. A script is a series of PowerShell commands that are linked together through the use of a single file. Commands can be executed sequentially with no user involvement.
Basic PowerShell Syntax
PowerShell has a reputation of being complex. However, this is not true.
Microsoft has attempted to make the syntax as uniform as possible. The
syntax is a verb-noun cmdlet. To see a list of all the commands that can
be used, use Get-Command
to get a comprehensive list of every
command in the default module.
To get a list of commands that start with Get, use the command
Get-Command Get-*
.
To obtain a better idea of the verb coverage, you can use the
Get-Command
cmdlet and pipe the results to the
Group-Object
cmdlet as shown here:
Get-Command -CommandType cmdlet | Group-Object -Property Verb | Sort-Object -Property count -Descending
When the previous command is run, the resulting output is displayed in the
following list. The command is run on Windows Vista and includes only the
default cmdlets; no modules are loaded. As shown in the listing, the verb
Get
is used the most often by the default cmdlets, followed
distantly by Set
, New
, and Remove
.
Count Name Group ----- ---- ----- 46 Get {Get-Acl, Get-Alias, Get-AuthenticodeSignatu... 19 Set {Set-Acl, Set-Alias, Set-AuthenticodeSignatu... 16 New {New-Alias, New-Event, New-EventLog, New-Ite... 14 Remove {Remove-Computer, Remove-Event, Remove-Event... 8 Export {Export-Alias, Export-Clixml, Export-Console... 8 Write {Write-Debug, Write-Error, Write-EventLog, W... 7 Import {Import-Alias, Import-Clixml, Import-Counter... 7 Out {Out-Default, Out-File, Out-GridView, Out-Ho... 6 Add {Add-Computer, Add-Content, Add-History, Add... 6 Start {Start-Job, Start-Process, Start-Service, St... 6 Invoke {Invoke-Command, Invoke-Expression, Invoke-H... 6 Clear {Clear-Content, Clear-EventLog, Clear-Histor... 5 Test {Test-ComputerSecureChannel, Test-Connection... 5 Stop {Stop-Computer, Stop-Job, Stop-Process, Stop... 4 ConvertTo {ConvertTo-Csv, ConvertTo-Html, ConvertTo-Se... 4 Register {Register-EngineEvent, Register-ObjectEvent,... 4 Format {Format-Custom, Format-List, Format-Table, F... 4 Disable {Disable-ComputerRestore, Disable-PSBreakpoi... 4 Enable {Enable-ComputerRestore, Enable-PSBreakpoint... 3 ConvertFrom {ConvertFrom-Csv, ConvertFrom-SecureString, ... 3 Wait {Wait-Event, Wait-Job, Wait-Process} 3 Update {Update-FormatData, Update-List, Update-Type... 3 Select {Select-Object, Select-String, Select-Xml} 3 Rename {Rename-Computer, Rename-Item, Rename-ItemPr... 2 Unregister {Unregister-Event, Unregister-PSSessionConfi... 2 Restart {Restart-Computer, Restart-Service} 2 Move {Move-Item, Move-ItemProperty} 2 Copy {Copy-Item, Copy-ItemProperty} 2 Measure {Measure-Command, Measure-Object} 1 Tee {Tee-Object} 1 Suspend {Suspend-Service} 1 Debug {Debug-Process} 1 Sort {Sort-Object} 1 Show {Show-EventLog} 1 Checkpoint {Checkpoint-Computer} 1 Split {Split-Path} 1 Disconnect {Disconnect-WSMan} 1 Use {Use-Transaction} 1 Pop {Pop-Location} 1 Where {Where-Object} 1 Trace {Trace-Command} 1 Exit {Exit-PSSession} 1 Enter {Enter-PSSession} 1 Undo {Undo-Transaction} 1 Receive {Receive-Job} 1 Read {Read-Host} 1 Compare {Compare-Object} 1 Convert {Convert-Path} 1 Connect {Connect-WSMan} 1 Join {Join-Path} 1 Push {Push-Location} 1 Complete {Complete-Transaction} 1 Limit {Limit-EventLog} 1 Resume {Resume-Service} 1 ForEach {ForEach-Object} 1 Send {Send-MailMessage} 1 Reset {Reset-ComputerMachinePassword} 1 Group {Group-Object} 1 Restore {Restore-Computer} 1 Resolve {Resolve-Path}
To clear the screen, use cls
.
To get a list of commands that deal with Service, use the command
Get-Command *-Service
.
Get-Service VSS | Start-Service
Getting Help
Get-Help
display help information.
To get help on a specific cmdlet, use Get-Help
cmdletname
. As an example, you can issue the command
Get-Help Get-VM
.
If the command is unknown, try using a search engine on the Internet.
Microsoft also has a website dedicated to PowerShell.
The PowerShell Gallery is a repository of third-party code. Note: In order to use the Microsoft PS Gallery as a trusted repository, use the following command:
Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Predicting a Command's Behavior
You may find a PowerShell command that may do what you want, but are unsure
as to what the consequences would be, this makes it difficult to use.
There is a command that shows you what will happen if a command is executed.
This is the -whatif
argument. As an example:
Start-Service -Name VSS -whatif
This does not execute the command. What it does do is show you messages as if the command was executed.
You can tell PowerShell to ask for confirmation before it attempts to perform
the command. This is done through the -confirm
argument.
-whatif
and -confirm
cannot be used on all
commands. To return a list of commands that accept the
-whatif
argument, use:
Get-Command | Where {$_.Definition -Like "*whatIf*"} Get-Command | Where {$_.Definition -Like "*Confirm*"}
Working with PowerShell Cmdlets
A cmdlet is a small bit of executable code that performs some
administrative task such as deleting a file, adding a user, or changing the
registry. Cmdlets are named with a verb-noun syntax with strict guidelines
for verb naming. An example cmdlet is Get-Process
, which
returns information about processes running on a machine.
To ensure consistency, the set of verbs that developers can use is restricted
through the use of formal guidance (and runtime checking that emits an error
if unapproved verbs are used in a cmdlet). That helps to ensure that the
"get" verb has the same semantics in Active Directory as in Exchange - and
that's the same semantics for Get-Process
.
Cmdlet nouns can vary more because they are task-specific. A cmdlet's noun,
however, should always be singular, possibly with a prefix to avoid
collision (where two product groups produce similarly named cmdlets
that do potentially different things). Quest's Active Directory tools use
the noun prefix QAD
, whereas Microsoft's Active Directory
cmdlets use the prefix AD
. So, although both cmdlet sets
provide a way to get a user in the AD, Quest's tool uses
Get-QADuser
, whereas Microsoft's cmdlet is
Get-AdUser
.
To some degree, learning the verbs Windows PowerShell uses for any given
task domain is easy - these are standard (Get
,
New
, Remove
, and so on). What differs are the
nouns, which are in effect the task domain objects. Thus, in Active
Directory (AD), you work with users (Get-AdUser
), groups
(Get-AdGroup
), and domains (Get-AdDomain
), whereas
in Lync Server you work with topology (Enable-CSTopology
),
analog device (Get-CSAnalogDevice
), location policy
(Get-CSLocationPolicy
), and so on.
Cmdlets can have aliases - shortcut names to simplify typing, particularly at
the command prompt. Thus, GPS
is an alias for
Get-Process
. Windows PowerShell comes with some built-in
aliases, but you can easily add your own aliases in profile files that run
each time you run Windows PowerShell.
Cmdlets can take parameters that tell the cmdlet how to work. The
Get-Process
cmdlet has a property, -Name
, which is
used to tell Windows PowerShell the name of the processes you want
information about. Cmdlet property names always begin with a hyphen
(-
) and are separated from the parameter value and other
parameters by a space.
Windows PowerShell provides you with parameter value globbing; that
is, specifying a parameter value with wildcards to match potentially more
than one object. Thus, you could issue the cmdlet Get-Process -Name
P*W
to get all the processes that begin with a "p" and have a "w"
somewhere later in the process name.
Parameter full names, which can get long in some cases, can also be abbreviated. Windows PowerShell lets you use the fewest number of characters necessary to distinguish one parameter name from all the others.
Commonly Used Cmdlets
Get-Process
This command is used to retrieve information about processes.
To see a list of processes and the amount of memory used, use the following command:
Get-Process | Select-Object Name, WS
WS is short for working set.
To see a list of processes and sort by the amount of memory used, use the following command:
Get-Process | Sort-Object WS
To see a list of processes and sort by the amount of memory used in descending order, use the following command:
Get-Process | Sort-Object WS -Descending | Select-Object Name, WS
To see a list of processes and sort by the amount of memory used in descending order and limit the list to the last five entries, use the following command:
Get-Process | Sort-Object WS -Descending | Select-Object Name, WS -Last 5
Get-Service
To get service name, display name and status for a particular service, like VSS, use the following:
Get-Service VSS | Select-Object Name, DisplayName, Status
To get service name, display name and status, format in a list, for a particular service, like VSS, use the following:
Get-Service VSS | Select-Object Name, DisplayName, Status | Format-List
To get service name, display name and status, format in a table, for a particular service, like VSS, use the following:
Get-Service VSS | Select-Object Name, DisplayName, Status | Format-Table
To start a service, like VSS, use the following:
Start-Service VSS
Type
To send the contents of a file to the screen, use
Type C:\Data\readme.txt
Get-Content
To send the contents of a file to the screen, use
Get-Content C:\Data\readme.txt
CLS
To clear the screen, use
CLS
Clear-Host
To clear the screen, use
Clear-Host
Copy-Item
To copy an item, like a file, use:
Copy-Item C:\Data\Readme.txt C:\Scripts
Get-ChildItem
This command is equivalent to the old DOS command dir
.
To view the directory entry for a file, use
Get-ChildItem C:\Scripts\Readme.txt
To get a listing for the current directory and the child directories, use the following:
Get-ChildItem -Recurse
Remove-Item
To delete a file, use
Remove-Item C:\Scripts\Readme.txt
Get-History
Display a list of all commands issued during this session, use:
Get-History
Objects and Attributes
PowerShell commands are able to perform and show much more information than what the GUI is able to provide. To select the objects that you want to have returned from a command, use the Select-Object
command. For example:
Get-Process | Select-Object *
This will return all of the information associated with a process. There are many more attribute available through PowerShell that are not available in Windows GUI.
The names of columns don't always match up to the names used in PowerShell. For instance, the Windows column named Description is callled DisplayName in the PowerShell command. To examine the services using columns Status, Name, and DisplayName, use:
Get-Services
To use the same command with all the columns, use:
Get-Services | Select-Object *
To use PowerShell to get a list of service dependencies use:
Get-Services | Select-Object Name, Status, ServicesDependedOn
To use PowerShell to get a list of service dependencies in table format use:
Get-Services | Select-Object Name, Status, ServicesDependedOn | Format-Table
Get-Services | Select-Object Name, Status, ServicesDependedOn | FT
To use PowerShell to get a list of service dependencies in list format use:
Get-Services | Select-Object Name, Status, ServicesDependedOn | Format-List
Get-Services | Select-Object Name, Status, ServicesDependedOn | FL
Working with Variables
All variables have a name. That name must start with a '$'. To create a string variable X and set it to 1, use:
$X="1"
To view the contents of a variable, just type the name:
$X
You can also use the following syntax:
Write-Host $X
To concatenate two string variables, use:
$X="1" $Y="1" $X + $Y
This returns a string value of "11".
To add to variables, use:
$X=1 $Y=1 $X + $Y
This returns a numerical value of 2.
To perform variable substitution, use the following:
$X=1 $Y=1 Write-Host $X + $Y
This returns the value '1 + 1'.
To perform the math, use:
$X=1 $Y=1 $Z = $X + $Y Write-Host $Z
This will return the sum of the two values...2.
$X="1" $Y="1" [int]$X + [int]$Y
This will treat the two string values as numbers and add them together.
Variables do not span PowerShell sessions.
Array variables
An array is 0-based.
$MyArray = "A", "B", "C", "D" Write-Host $MyArray Write-Host $MyArray[3]
$CN = Get-Command
This places each command into an entry in the array.
The followng command will display the number of PowerShell commands available on this machine:
$CN = Get-Command $CN.count
To build a list of virtual machines in an array:
$VirtualMachine = Get-VM $VirtualMachine $VirtualMachine.count
PowerShells Built-In Variable
You can enumerate PowerShell's variables with this command:
Get-Variable | Format-Table name, value -auto
Name Value ---- ----- $ } ? True ^ Get-WmiObject _ args {} ConfirmPreference High ConsoleFileName DebugPreference SilentlyContinue Error {} ErrorActionPreference Continue ErrorView NormalView ExecutionContext System.Management.Automation.EngineIntrinsics false False FormatEnumerationLimit 4 HOME C:\Users\Rodney Host System.Management.Automation.Internal.Host.InternalHost input System.Collections.ArrayList+ArrayListEnumeratorSimple Matches {0} MaximumAliasCount 4096 MaximumDriveCount 4096 MaximumErrorCount 256 MaximumFunctionCount 4096 MaximumHistoryCount 64 MaximumVariableCount 4096 MyInvocation System.Management.Automation.InvocationInfo NestedPromptLevel 0 null OutputEncoding System.Text.ASCIIEncoding PID 2956 PROFILE C:\Users\Rodney\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 ProgressPreference Continue PSBoundParameters {} PSCulture en-US PSEmailServer PSHOME C:\Windows\System32\WindowsPowerShell\v1.0 PSSessionApplicationName wsman PSSessionConfigurationName http://schemas.microsoft.com/powershell/Microsoft.PowerShell PSSessionOption System.Management.Automation.Remoting.PSSessionOption PSUICulture en-US PSVersionTable {CLRVersion, BuildVersion, PSVersion, WSManStackVersion...} PWD C:\Scripts ReportErrorShowExceptionClass 0 ReportErrorShowInnerException 0 ReportErrorShowSource 1 ReportErrorShowStackTrace 0 ShellId Microsoft.PowerShell StackTrace this true True VerbosePreference SilentlyContinue WarningPreference Continue WhatIfPreference False
$_. Variable
Constructions such as ... | Where {$_.name -Match "win"}
are
incredibly useful in PowerShell. Definitions such as: '$_
means in this pipeline', are a bit stuffy. The best way to understand
$_
is to work through examples.
First, $_
is a variable or placeholder. Consider the following:
Get-Service | Where-Object {$_.name -Match "win"}
In this example, we are getting the services, where the service name matches
'Win'. $_
saves us repeating Get-Service
, or
whatever else may be to the left of ... | Where{$_
. The
.dot
command introduces a property.
In the next example, list all the WMI Objects that have the word 'Network' in the name:
Get-WmiObject -List | Where-Object {$_.name -Match 'Network'}
Introduction to PowerShell Modules
Windows PowerShell 2.0 introduced the concept of modules. A module is a package that contains Windows PowerShell cmdlets, aliases, functions, variables, and even providers. In short, a Windows PowerShell module can contain the types of items that you might put into your profile.
In its most basic form, a Windows PowerShell module is a file that contains the same type of code written in a PowerShell script. Many Windows PowerShell modules begin as a PowerShell script and end as modules, with little or no modification other than changing the file extension and location of the file.
Windows PowerShell modules exist in two states: loaded and unloaded. To
display a list of all loaded modules, you can use the Get-Module
cmdlet without any parameters as shown here.
To display the current default module that is currently loaded, use:
Get-Module
This will return the following:
ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Manifest 3.1.0.0 Microsoft.PowerShell.Management {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Con...
PowerShell 2.0
If no modules are loaded, nothing is displayed to the Windows PowerShell console. No errors are displayed, and there is no confirmation that the command was actually run as shown here.
PS C:\> Get-ModulePS C:\>
To get the information for a specific module, use:
Get-Module -Name Microsoft.PowerShell.Management | Format-List
This will return the following:
Name : Microsoft.PowerShell.Management Path : C:\windows\system32\windowspowershell\v1.0\Modules\Microsof t.PowerShell.Management\Microsoft.PowerShell.Management.psd 1 Description : ModuleType : Manifest Version : 3.1.0.0 NestedModules : {Microsoft.PowerShell.Commands.Management.dll} ExportedFunctions : ExportedCmdlets : {Add-Computer, Add-Content, Checkpoint-Computer, Clear-Content...} ExportedVariables : ExportedAliases :
To load a module, use the following command:
Import-Module Hyper-V Import-Module ServerManager
At this point, if the list of modules is listed again, there are additional modules loaded.
When a command is executed, PowerShell attempts to locate modules that contains that command. When found, it loads that module and then executes the command. Older versions of PowerShell do not have this funtionality. Also PowerShell needs to know about the modules before this functionality can be used.
To remove a module, use the following command:
Remove-Module -Name Hyper-V
To list all of the commands that are present in a module, use:
Get-Command -Module Hyper-V
A more complex example:
$VM = Get-VM -Name "Exch3" $VMHost = Get-VMHost -ComputerName "Hyper-V-2.mgmt.com" $HostRating = Get-VMHostRating -VM $VM -VMHost $VMHost $HostRating
Making Sense of Error Messages
Basic PowerShell Scripting
Building PowerShell Scripts
A script is a text file that has a file extension of .ps1
. That
script contains one or more PowerShell commandlets. Scripts can be stored
in any directory. But as a Best Practice, it is best to store scripts in a
central repository. A good place to store them is C:\Scripts
.
To execute a script from within PowerShell, use:
./scriptname.ps1
Configuring Execution Policies
An execution policy is a security measure used to prevent malicious scripts from executing. Depending on your execution policy, it may prevent your scripts from executing. To view the current execution policy, use:
Get-ExecutionPolicy
The Set-ExecutionPolicy cmdlet changes the user preference for the Windows PowerShell execution policy. To set the current execution policy, use:
PowerShell 2.0
Set-ExecutionPolicy [-ExecutionPolicy] [Restricted|AllSigned|RemoteSigned|Unrestricted]
PowerShell 5.0
Set-ExecutionPolicy [-ExecutionPolicy] [Restricted|AllSigned|RemoteSigned|Unrestricted|Bypass|Undefined]
Note: Some forms of this command may require an elevated, or administrative, level of permission. To resolve this issue, PowerShell must be started from the command line as administrator. This would be evident with a message such as:
Set-ExecutionPolicy : Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft .PowerShell' is denied. At line:1 char:20 + Set-ExecutionPolicy <<<< -ExecutionPolicy Unrestricted -Scope LocalMachine + CategoryInfo : NotSpecified: (:) [Set-ExecutionPolicy], UnauthorizedAccessException + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.SetExecutionPolicyComma nd
The possible execution policy values are:
- Restricted: Does not load configuration files or run scripts. "Restricted" is the default execution policy.
- AllSigned: Requires that all scripts and configuration files be signed by a trusted publisher, including scripts that you write on the local computer.
- RemoteSigned: Requires that all scripts and configuration files downloaded from the Internet be signed by a trusted publisher.
- Unrestricted: Loads all configuration files and runs all scripts. If you run an unsigned script that was downloaded from the Internet, you are prompted for permission before it runs.
- Bypass: Nothing is blocked and there are no warnings or prompts.
- Undefined: Removes the currently assigned execution policy from the current scope. This parameter will not remove an execution policy that is set in a Group Policy scope.
The scope of an execution policy defines what the execution policy effects.
- MachinePolicy
- UserPolicy
- Process: The execution policy affects only the current Windows PowerShell process.
- CurrentUser: The execution policy affects only the current user.
- LocalMachine: The execution policy affects all users of the computer.
To set the current Windows PowerShell process to unrestrictive, use:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process
To see the scope of the current execution policy, use:
Get-ExecutionPolicy -List
Adding Functions to PowerShell Scripts
We want to create a function to clear the screen and write the string 'Hello World!' on the screen.
#****************************************************************************** #* This is a comment line. * #****************************************************************************** Function Display-HelloWorld { Write-Host "The function is now executing." Write-Host "Hello World!" } CLS Write-Host "The main script body is now executing." Display-HelloWorld Write-Host "The function has completed and the main body is now executing."
The concept and use of returning values in functions is unusual. In Windows
PowerShell, the results of each statement are returned as output, even
without a statement that contains the Return
keyword. The
Return
keyword really just indicates a lgical exit point.
Consider the following example:
$price return
has the exact same effect as:
return $price
Example Add the number 5 and return the value:
function demoadd { param ($value) "Adding five" $value += 5 return $value } C:\PS> $result = demoadd 2 C:\PS> C:\PS> $result Adding five 7
The key point to note in the above example is that the "Adding 5" string is not displayed, but is instead assigned to the $result variable and returned along with the number.
Silencing Errors
What are common parameters? These are the common parameters that are
associated with a vast number of commandlets. To make an error disappear,
use the argument -ErrorAction SilentlyContinue
. If you use the
option -ErrorAction Stop
, the commandlet halts execution
when an issue is raised. The -ErrorAction Continue
can show an
error and continue processing. When -ErrorAction Inquire
is
used, the user is queried every time an error occurs.
Using Interactive Authentication
Authentication errors can occur if a script is executed by somebody who is not authorized. A script could query the user for creditials when needed:
$Cred = Get-Credential Get-WmiObject Win32-DiskDrive -ComputerName "mydemo-dc" -Credential $Cred
Using Automatic Authentication
Instead of relying on a user to supply the script a password every time it executes, a secure passworld file could be used.
To read input from the screen and output that information to a secure password file, use:
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Scripts\password.txt
This will wait for the user to input a series of keys that will be captured
and written to the password.txt
file. If the text file is
opened, it will contain a cryptic character string that represents password.
Now go back to the script used in the last section.
$Username = "MyDemo\Administrator" $Password = Get-Content C:\Scripts\password.txt | ConvertTo-SecureString $Cred = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $Username, $Password Get-WmiObject Win32-DiskDrive -ComputerName "mydemo-dc" -Credential $Cred
Enhancing PowerShell Scripts
Passing Variables to Functions
#****************************************************************************** #* This is a comment line. * #****************************************************************************** Function Get-MyVMs($Server) { Write-Host Write-Host "Hyper-V Host Server Name is: " Write-Host $Server Write-Host "The virtual machines on this server are:" Get-VM -ComputerName $Server | Select-Object Name } $Server = "Hyper-V-1" Get-MyVMs $Server $Server = "Hyper-V-12 Get-MyVMs $Server
Global Variables and Local Variables
Creating Loops
$Cars = @("Ford", "Chevy", "Dodge") ForEach ($Car in $Cars) { Write-Host $Car }
Ford Chevy Dodge
Let's revisit an earlier script and convert it to a loop:
#****************************************************************************** #* This is a comment line. * #****************************************************************************** Function Get-MyVMs($Servers) { Write-Host ForEach ($Server in $Servers) { Write-Host "Hyper-V Host Server Name is: " Write-Host $Server Write-Host Write-Host "The virtual machines on this server are:" Get-VM -ComputerName $Server | Select-Object Name } } #****************************************************************************** #* Main script body starts here. * #****************************************************************************** Write-Host $Servers = @("Hyper-V-1", "Hyper-V-2", "Hyper-V-3") Get-MyVMs $Servers
Working with .NET Integraton
PowerShell is perfectly capable of performing math functions. For instance,
on a PowerShell command line, entering 2+2
will yield the result
of 4
. Subsequently, subtraction, multiplication and division
all work. However, when it comes time to use exponents, 2^2
will generate an error. PowerShell can only do basic arithmetic. However,
by tapping into .NET, it is possible to extend PowerShell's capabilities.
PowerShell utilizes a hierarchtical structure. It is:
NameSpaces Assemblies Classes Methods
To extend PowerShell, the concept of Classes and Methods must be understood. A class is a unit of functionality. A method is an inidividual component within that class. The Math class will be used here.
To find the squareroot of 64, call the class' static method:
[Math]::SQRT(64)
This will return the value of 8
. The [Math]
is the
name of the class that we wish to use. The next part was the method name.
So, the command structure is:
[classname]::methodname()
To determine the methods that are available for a class, use:
[System.Math].GetMethods() [System.Math].GetMethods() | Select-Object Name [System.Math].GetMethods() | Select-Object Name -Unique
To view a method that is overloaded with multiple parameter sets, use:
[System.IO.File]::ReadAllText
A constructor is used along with New-Object
to actually build a
class with some values already defined. A class might have multiple constructors in it
to allow for various approaches to building out the class object. So how can we determine
what kind of constructors are available? Search for the class on the MSDN website. You
can also use the following command:
Get-Constructor -TYPE Net.Sockets.TCPClient
PowerShell 5.0
There is a built-in method applied to all of the classes called New()
. It is
used to build an object vs. using New_Object. If you do not supply the parenthesis, it
will actually display all of the available constructors.
[Net.Sockets.TCPClient]::New()
We can bring this all together by creating an object using a constructor and then making use of one of the methods to perform an action. For this example, I will make use of the System.DateTime class to create a class and then make use of the method available in the class.
#****************************************************************************** #* Create the object using a constructor with a Year, Month and Day * #* parameter. * #****************************************************************************** $DateTime = New-Object System.DateTime -ArgumentList 2015, 10, 10 #****************************************************************************** #* Display the object. * #****************************************************************************** $DateTime #****************************************************************************** #* View all of the properties. * #****************************************************************************** $DateTime | Select-Object -Property * #****************************************************************************** #* Use a method to convert the DateTime to a FileTime type. * #****************************************************************************** $DateTime.ToFileTime() #****************************************************************************** #* Add seven days to the currently defined Date. * #****************************************************************************** $DateTime.AddDays(7)
To determine the version of .NET that you are using using the following commands:
PowerShell 1.0
[System.Environment]::Version
PowerShell 2.0
$PSVersionTable.CLRVersion
Building Stand-Alone Functions
It is possible to take a function that you have written and make it available to other scripts. This is done through the creation of a module. This will extend PowerShell's functionality.
A module can live anywhere. However, by putting modules in one of two
predefined locations, Windows PowerShell is able to import the module more
easily. These locations are stored in the
$env:PSModulePath
environment variable, which can be changed to
include additional locations. By default, $env:PSModulePath
includes locations at $psHome\Modules
and
$env:UserProfile\Documents\WindowsPowerShell\Modules
.
By default, the modules are located and search in the following order:
C:\Users\username\Documents\WindowsPowerShell\Modules C:\Program Files\WindowsPowerShell\Modules C:\Windows\System32\WindowsPowerShell\v1.0\Modules
Create a directory for your module. That folder name must use the same name
as the module. The create a text file in that directory with the same name.
The file extension must be .psm1
. A module can contain one or
more functions.
Function Test-Code { Write-Host Write-Host "The function works!" Write-Host } Export-ModuleMember -Function 'Test-Code'
Once the text file is created and saved, the module would need to be imported:
Import-Module MyModule
To get a list of commandlets that are included in a module, use:
Get-Command -Module MyModule
To obtain a listing of all modules that are available on the system but are
not loaded into the Windows PowerShell console, you can use the
Get-Module
cmdlet with the -ListAvailable
parameter
as shown here.
Get-Module -ListAvailable Import-Module Hyper-V Get-Module Get-Command -Module Hyper-V
Interacting with Active Directory
Querying Active Directory from PowerShell
Creating Active Directory User Accounts with PowerShell
Modifying Active Directory User Accounts with PowerShell
Working with Active Directory Groups from Powershell
Automating PowerShell Scripts
Making Scripts Run Automatically
Let's say there is a Windows service that is either not starting or shutting down unexpectedly. You need to be notified when this occurs. This cal be done with a script that execute periodically that checks the status of that service.
$VSS = Get-Service VSS $VSS.Status If ($VSS.Status -EQ 'Stopped') { Start-Service VSS #**************************************************************************** #* We need a delay here. The -S signifies 'seconds' and the 10 indicates * #* 10 units. so the -S 10 is '10 seconds'. We are doing this to give the * #* service ample time to start. * #**************************************************************************** Start-Sleep -S 10 Get-Service Vss }
Now that we have a script that starts the service if it is stopped, the next
step is to use the Windows Task Scheduler. To set this up, on the Action
menu (right side), click on Create Task... This will open the Create Basic
Task Wizard. Enter a name and description. Tell the task to execute daily
at any particular time and to recur daily. For the Action, tell the task to
start a program. The Program/script is set to powershell.exe. In the
Arguments text box, type -File c:\Scripts\script.ps1
. Click
next to the Finish screen. Click the Finish button.
Sending E-Mail Messages from PowerShell Scripts
The first thing to do is to create a password file. Chances are, this script will need to generate an email and will need to run in an automated fashion. Therefore, a password file is needed.
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File C:\Scripts\password.txt
Next, build a script:
$Username = "servername\Administrator" $Password = Get-Content C:\Scripts\password.txt | ConvertTo-SecureString $Cred = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $Username, $Password Send-MailMessage -To [email protected] -From [email protected] -Subject "Test Message" -Body "This message was generated by PowerShell." -Credential $Cred -SMTPServer Exch1.mail.com
Generating Meaningful E-Mail Messages
The script used in Lesson 6-1 and Lesson 6-2 can be combined to create a script that is both useful and meaningful.
$EmailTo = "[email protected]" $EmailFrom = "[email protected]" $Subject = "VSS Service Health" $SMTPServer = "Exch1.mail.com" $Username = "servername\Administrator" $Password = Get-Content C:\Scripts\password.txt | ConvertTo-SecureString $Cred = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $Username, $Password Function Send-Notice { Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $Subject -Body $Body -Credential $Cred -SMTPServer $SMTPServer } Function Check-ServiceStatus { $VSS = Get-Service VSS $VSS.Status If ($VSS.Status -EQ 'Stopped') { $Body = "The VSS Service has stopped." Send-Notice $Body Start-Service VSS #************************************************************************** #* We need a delay here. The -S signifies 'seconds' and the 10 indicates * #* 10 units. So the -S 10 is '10 seconds'. We are doing this to give * #* the service ample time to start. * #************************************************************************** Start-Sleep -S 10 } $VSS = Get-Service VSS If ($VSS.Status -EQ 'Running') { $Body = "The VSS Service is running." Send-Notice $Body } } Check-ServiceStatus
Best Practices for PowerShell Scripting
PowerShell best practices are vague and very individual. There are no rigid set of best practices available.
#****************************************************************************** #* We need a delay here. The -S signifies 'seconds' and the 10 indicates * #* 10 units. So the -S 10 is '10 seconds'. We are doing this to give the * #* service ample time to start. * #****************************************************************************** # Declare variables $EmailTo = "[email protected]" $EmailFrom = "[email protected]" $Subject = "VSS Service Health" $SMTPServer = "Exch1.mail.com" $Username = "servername\Administrator" $Password = Get-Content C:\Scripts\password.txt | ConvertTo-SecureString $Cred = New-Object -Typename System.Management.Automation.PSCredential -ArgumentList $Username, $Password #****************************************************************************** #* This function receives the $Body variable, which contains the message * #* body. It then sends an E-mail message to the recipient defined by the * #* $EmailTo variable. * #****************************************************************************** Function Send-Notice { Send-MailMessage -To $EmailTo -From $EmailFrom -Subject $Subject -Body $Body -Credential $Cred -SMTPServer $SMTPServer } #****************************************************************************** #* This function checks to see if the VSS service is running. * #****************************************************************************** Function Check-ServiceStatus { $VSS = Get-Service VSS $VSS.Status If ($VSS.Status -EQ 'Stopped') { $Body = "The VSS Service has stopped." Send-Notice $Body Start-Service VSS #************************************************************************** #* We need a delay here. The -S signifies 'seconds' and the 10 indicates * #* 10 units. so the -S 10 is '10 seconds'. We are doing this to give * #* the service ample time to start. * #************************************************************************** Start-Sleep -S 10 } $VSS = Get-Service VSS If ($VSS.Status -EQ 'Running') { $Body = "The VSS Service is running." Send-Notice $Body } } #****************************************************************************** #* Script body. * #****************************************************************************** Check-ServiceStatus
Using PowerShell as a Reporting Tool
Basic PowerShell Reporting
Creating CSV Files
Creating Text Files
Creating HTML Files
Adding Color and Formatting to HTML Reports
Creating Graphical Reports
Creating Simple Charts Using PowerShell
Changing Chart Types
Importing Data Into PowerShell Charts
Using PowerShell Remoting
Introduction to PowerShell Remoting
PowerShell is Windows preferred method for server management. Remote management allows someone to manage each of those servers without having to phyically log on to each of those servers. It is possible to execute a command once on a group of servers.
The following command returns the name of the host computer:
Get-VMHost
There are three methods to redirect a command to another server. The first
method uses the -ComputerName
parameter. However, not every cmdlet support
the use of the -ComputerName
parameter. The next method is something called
the invoke command
. The invoke
command can be used to send multiple commands
to a single server. The third method is something called a PS Session. PS
Session is essentially a remote PowerShell session. The entire console
remotes itself to another machine. Anything typed into the console is
executed on that remote machine.
Establishing Remote Sessions
In order to establish a session on a remote system, it is necessary to enable this functionality on the remote system. To do this, log on to the remote Windows machine, open up PowerShell and execute the following command:
Enable-PSRemoting -Force
Let's get back to the task at hand, establishing a remote session. Back on your system, open up PowerShell and drop down to the root folder:
cd \
Next, generate a list of machines. In this example, we are using virtual machines, so use:
Get-VM
Here are the next commands:
$Cred=Get-Credential
This opens a dialog to enter in a user name and password.
User Name: mgmt\Administrator Password: **********
The user name and password are now in a variable called $Cred. Next:
Enter-PSSession -ComputerName Hyper-V-3 -Credential $Cred
If all goes well, your prompt will change and you will now be connected to your remote system. You are now within a console on that machine. To get out of your remote session, use:
Exit-PSSession
You are now back to your local machine.
If there are any issues that prevent a connection to a remote machine, the information on this website proved to be extremely helpful in fixing the problem.
Tip: Enable and Use Remote Commands in Windows PowerShell
Running Cmdlets on Remote Systems
Compiling Data from Remote Servers
There is a trick to using variables in a remote session and making that information available in local sessions. It is not hard...but there is a trick to it.
Consider the following script:
$Session = New-PSSession -ComputerName Hyper-V-3 Invoke-Command -Session $Session -ScriptBlock { $myVar = Get-VM Write-Host "The script is currently executing on a remote session." $myVar | Select-Object Name Exit-PSSession } Write-Host "The script is not curretly executing a remote session." $myVar | Select-Object Name
The last line will NOT display a value for $myVar because it is out of scope. The following code will fix the issue.
$Session = New-PSSession -ComputerName Hyper-V-3 Invoke-Command -Session $Session -ScriptBlock { $myVar = Get-VM Write-Host "The script is currently executing on a remote session." $myVar | Select-Object Name Exit-PSSession } $LocalResult = Invoke-Command -Session $Session - ScriptBlock {$myVar} Exit-PSSession Write-Host "The script is not curretly executing a remote session." $LocalResult | Select-Object Name
Building Your Own PowerShell GUI
Creating Basic GUIs
Adding Text Boxes
Working with Buttons
Working with Drop-Down Lists
How to start the Windows PowerShell 2.0 Engine
When you start Windows PowerShell the newest version starts by default. To start Windows PowerShell with the Windows PowerShell 2.0 Engine, use the Version parameter of PowerShell.exe. You can run the command at any command prompt, including Windows PowerShell and Cmd.exe.
PowerShell.exe -version 2
Windows API
- Use PowerShell to Interact with the Windows API: Part 1
- Use PowerShell to Interact with the Windows API: Part 2
- Use PowerShell to Interact with the Windows API: Part 3