PowerShell has reached a point where it has split into Windows PowerShell and PowerShell Core. Windows PowerShell accounts for versions up to, and including, PowerShell 5.1. Windows PowerShell is based on the .NET full framework. PowerShell Core accounts for version 6 and over and is based on the .NET core framework.
The future of PowerShell is in PowerShell Core; it opens up cross-platform scripting with PowerShell, that is, support for Linux and macOS.
As well as the change to .NET, there are an increasing number of differences between Windows PowerShell and PowerShell Core that must be accounted for.
The differences between Windows PowerShell and PowerShell Core will be highlighted throughout this book.
This book is split into a number of sections. Much of this book is intended to act as a reference. We will cover the following topics in this book:
- Exploring PowerShell fundamentals
- Working with data
- Automating with PowerShell
- Extending PowerShell
In the first section of this book, while exploring the PowerShell fundamentals, we will look at the use of language and cover as many building blocks as possible.
In this chapter, we will briefly look at a number of short, diverse topics:
- What is PowerShell?
- PowerShell editors
- Getting help
- Command naming
- Command discovery
- Parameters and parameter sets
- Introduction to providers
- Introduction to splatting
PowerShell is a mixture of a command line, a functional programming language, and an object-oriented programming language. PowerShell is based on Microsoft .NET, which gives it a level of open flexibility that was not available in Microsoft's scripting languages (such as VBScript or batch) before this.
PowerShell is an explorer's scripting language. With built-in help, command discovery, and with access to much of the .NET framework, it is possible to dig down through the layers.
This book is based on PowerShell Core 6.1 with references to PowerShell 5.1; some of the features that are discussed in this book may not be available in the earlier versions of PowerShell.
PowerShell Core may be installed side by side with Windows PowerShell. Preview versions of PowerShell Core can often be installed side by side with full releases of PowerShell Core.
While it is possible to write for PowerShell using the notepad application alone, it is rarely desirable. Using an editor that was designed to work with PowerShell can save a lot of time.
Specialized PowerShell editors such as Visual Studio Code (VS Code), PowerShell Studio, and PowerShell ISE offer automatic completion (IntelliSense), which reduces the amount of cross-referencing required while writing code. Finding a comfortable editor early on is a good way to ease into PowerShell; memorizing commands and parameters is not necessary.
PowerShell ISE is not planned to be released to support PowerShell 6 at this time. VS Code is the most commonly recommended editor for PowerShell. VS Code is a free open source editor that was published by Microsoft VS Code and may be downloaded fromhttp://code.visualstudio.com.
The PowerShell extension should be installed, and other extensions may be found on the marketplace:Â https://marketplace.visualstudio.com/VSCode.
VS Code provides support for PowerShell Core; the following screenshot shows how to change the version of PowerShell that's used when editing a script:

Gaining confidence using the built-in help system is an important part of working with PowerShell. In PowerShell, help is extensive; authors can easily write their own help content when working with functions, scripts, and script modules.
A number of commands are available to interact with the help system, as follows:
Get-Help
Save-Help
Update-Help
Before exploring these commands, the concept of Updatable help should be discussed, as help may not be present on a system after installation.
Updatable help was introduced with PowerShell 3. It gives authors the option to store the most recent versions of their help documentation outside of PowerShell on web servers.
Note
Which modules support updatable help?
A list of modules that support updatable help may be viewed by running the following command: Get-Module -ListAvailable | Where-Object HelpInfoURI -like *
.
Help for the core components of PowerShell is no longer a part of the Windows Management Framework package and must be downloaded before it can be viewed. The first time Get-Help
is run, you will be prompted to update help.
If the previous prompt is accepted, PowerShell will attempt to download content for any module that supports updatable help.
Computers with no internet access or computers behind a restrictive proxy server may not be able to download the help content directly. The Save-Help
command, which will be discussed later in this section, may be used to work around this problem. If PowerShell is unable to download help, it can only show a small amount of information about a command; for example, without downloading help, the content for the Out-Null
command is minimal, as shown here:
PS> Get-Help Out-Null NAME Out-Null SYNTAX Out-Null [-InputObject <psobject>] [<CommonParameters>] ALIASES None REMARKS Get-Help cannot find the Help files for this cmdlet on this computer. It is displaying only partial help. -- To download and install Help files for the module that includes this cmdlet, use Update-Help. -- To view the Help topic for this cmdlet online, type: "Get-Help Out-Null -Online" or go to http://go.microsoft.com/fwlink/?LinkID=113366.
Updatable help as a help
file may be viewed using the following command:
Get-Help about_Updatable_Help
Without any arguments or parameters, Get-Help
will show introductory help about the help system. This content is taken from the default help
file (Get-Help default
); a snippet of this is as follows:
PS> Get-Help
TOPIC
Windows PowerShell Help System
SHORT DESCRIPTION
Displays help about Windows PowerShell cmdlets and concepts.
LONG DESCRIPTION
Windows PowerShell Help describes Windows PowerShell cmdlets,
Note
The help content can be long
The help content, in most cases, will not fit on a single screen. The help
command differs from Get-Help
in that it pauses (waiting for a key to be pressed) after each page, for example: help default
.
The previous command is equivalent to running Get-Help
and piping it into the more
command:
Get-Help default | more
Alternatively, in Windows PowerShell, but not PowerShell Core, Get-Help
can be asked to show a window:
Get-Help default -ShowWindow
The available help content may be listed using either of the following two commands:
Get-Help *
Get-Help -Category All
Help for a command may be viewed as follows:
Get-Help <CommandName>
Let's look at an example:
Get-Help Get-Variable
If a help document includes an online version link, it may be opened in a browser by using this:
Get-Help Get-Command -Online
The help content is broken down into a number of visible sections: name, synopsis, syntax, description, related links, and remarks. Syntax is covered in the following section in more detail as it is the most complex.
The syntax section lists each of the possible combinations of parameters a command will accept; each of these is known as a parameter set.
A command that has more than one parameter set is displayed as follows:
SYNTAX Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-FileVersionInfo] [-Module] [<CommonParameters>] Get-Process [-ComputerName [<String[]>]] [-FileVersionInfo] [-Module] -InputObject <Process[]> [<CommonParameters>]
The syntax elements written in square brackets are optional; for example, syntax help for Get-Process
shows that all of its parameters are optional, as shown in the following code:
SYNTAX Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-FileVersionInfo] [-Module] [<CommonParameters>]
Get-Process
may be run without any parameters at all, or it may be run with a value only and no parameter name, or it may include the parameter name as well as the value. Each of the following examples is a valid use of Get-Process
:
Get-Process
Get-Process powershell
Get-Process -Name powershell
Note
Get-Command can show syntax
Get-Command
may be used to quickly view the syntax for a command, for example, by running the following code: Get-Command Get-Variable -Syntax
.
Later in this chapter, we will take a more detailed look at the different parameters and how they might be used.
The examples section of help is often invaluable. In some cases, a command is sufficiently complex to require a detailed example to accompany parameter descriptions; in others, the command is simple, and a good example may serve in lieu of reading the help documentation.
Examples for a command may be requested using Get-Help
, as shown in the following example:
Get-Help Get-Process -Examples
It is common for a command to list several examples of its use, especially if the command has more than one parameter set.
Help for specific parameters may be requested as follows:
Get-Help Get-Command -Parameter <ParameterName>
This option allows for the quick retrieval of specific help for a single parameter; for example, help for the Path
parameter of the Import-Csv
command may be quickly viewed:
PS> Get-Help Import-Csv -Parameter Path
-Path [<String[]>]
Specifies the path to the CSV file to import. You can also pipe
a path to Import-Csv.
Required? false
Position? 1
Default value None
Accept pipeline input? true (ByValue)
Accept wildcard characters? false
The Detailed
switch parameter asks Get-Help
to return the most help content. This adds information about each parameter and the set of examples to name, synopsis, syntax, and description. Related links are excluded when using this parameter.
The Detailed
parameter is used as follows:
Get-Help Get-Process -Detailed
Using a Full
switch adds more technical details (compared to using the Detailed
parameter). Inputs, outputs, notes, and related links are added to those that are seen using Detailed
. For example, the sections detailing input and output types from Get-Process
may be extracted from the full help document:
PS> Get-Help Get-Process âFull ... INPUTS System.Diagnostics.Process You can pipe a process object to Get-Process. OUTPUTS System.Diagnostics.Process, System.Diagnotics.FileVersionInfo, System.Diagnostics.ProcessModule By default, Get-Process returns a System.Diagnostics.Process object. If you use the FileVersionInfo parameter, it returns a System.Diagnotics.FileVersionInfo object. If you use the Module parameter (without the FileVersionInfo parameter), it returns a
The Save-Help
command can be used with modules that support updatable help. It saves help content for modules to a folder; for example, the help content for the DnsClient
module can be saved to C:\PSHelp
(the directory must already exist):
Save-Help -DestinationPath C:\PSHelp -Module DnsClient
Alternatively, the help content for all modules may be saved as follows:
Save-Help -DestinationPath C:\PSHelp
The process creates an XML formatted HelpInfo
file that holds the source of the help content and a CAB (cabinet) file that's named after the module and culture.
Opening the CAB
file shows that it contains a number of XML formatted help
files, as shown in the following screenshot:

Saved help content can be copied over to another computer and imported using Update-Help
. This technique is very useful for computers that do not have internet access as it means help content can be made available.
The Update-Help
command can perform two tasks:
- Update
help
files from the internet - Import previously saved
help
files
Â
To update help from the internet, Update-Help
may be run without any parameters:
Update-Help
Note
Administrator rights are required
Updating help for some modules will require administrative rights (run as administrator). This applies to modules that are stored in protected areas of the filesystem, such as those in $PSHost (%SystemRoot%\System32\WindowsPowerShell\v1.0)
or under program files.
When updating help information from the internet, by default, Update-Help
will not download help content more than once every 24 hours
. This restriction is documented in the help
command and may be seen in action when using the Verbose
switch:
PS> Update-Help -Module DnsClient -Verbose
VERBOSE: Help was not updated for the module DnsClient, because the Update-Help command was run on this computer within the last 24 hours.
To update help again, add the Force parameter to your command.
As described in the preceding message, using the Force
switch parameter will ignore the time restriction. Importing help from a set of saved files uses the SourcePath
parameter:
Update-Help -SourcePath C:\temp
The following error message may be generated when attempting to import help from another culture:
PS> Update-Help -SourcePath C:\Temp -Module DnsClient
Update-Help : Failed to update Help for the module(s) 'DnsClient' with UIculture(s) {en-GB} :
Unable to retrieve the HelpInfo XML file for UI culture en-GB. Make sure the HelpInfoUri property in the module manifest is valid or check your network connection and then try the command again.
At line:1 char:1
+ Update-Help -SourcePath C:\Temp -Module DnsClient -Verbose -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ResourceUnavailable: (:) [Update-Help], Exception
+ FullyQualifiedErrorId : UnableToRetrieveHelpInfoXml,Microsoft.PowerShell.Commands.UpdateHelpCommand
The culture of the computer in question is set to en-GB
(Get-UICulture
), but the help files are for en-US
.
It is possible to work around this problem with the UICulture
parameter for Update-Help
, as follows:
Update-Help -SourcePath C:\Temp -Module DnsClient -UICulture en-US
About
documents describe features of a language or concepts that apply to more than one command. These items do not fit into help for individual commands.
Note
PowerShell Core: Where is About?
The PowerShell Core help files are not available as I write this at the time of writing. The examples that are shown here can only be applied to PowerShell 5.1 or lower.
The list of help files may be viewed by running Get-Help
with the category as HelpFile
, as demonstrated in the following code:
Get-Help -Category HelpFile
These files cover a huge variety of topics from aliases, to modules, to WMI:
Name Category Synopsis ---- -------- -------- about_Aliases HelpFile SHORT DESCRIPTION about_Arithmetic_Operators HelpFile SHORT DESCRIPTION about_Arrays HelpFile SHORT DESCRIPTION about_Assignment_Operators HelpFile SHORT DESCRIPTION about_Automatic_Variables HelpFile SHORT DESCRIPTION about_Break HelpFile SHORT DESCRIPTION about_Classes HelpFile SHORT DESCRIPTION about_Command_Precedence HelpFile SHORT DESCRIPTION about_Command_Syntax HelpFile SHORT DESCRIPTION about_Comment_Based_Help HelpFile SHORT DESCRIPTION about_CommonParameters HelpFile SHORT DESCRIPTION about_Comparison_Operators HelpFile SHORT DESCRIPTION about_Continue HelpFile SHORT DESCRIPTION about_Core_Commands HelpFile SHORT DESCRIPTION about_Data_Sections HelpFile SHORT DESCRIPTION ...
Commands in PowerShell are formed around verb and noun pairs in the form verb-noun.
This feature is useful when finding commands; it allows you to make educated guesses so that there is little need to memorize long lists of commands.
The list of verbs is maintained by Microsoft. This formal approach to naming commands greatly assists in discovery.
Verbs are words such as Add
, Get
, Set
, and New
. In addition to these, we have ConvertFrom
and ConvertTo
.
The list of verbs that are available in PowerShell can be accessed as follows:
Get-Verb
Each verb has a group, such as data, life cycle, or security. Complementary actions such as encryption and decryption tend to use verbs in the same group; for example, the verb Protect
may be used to encrypt something and the verb Unprotect
may be used to decrypt something.
Note
Verb descriptions
A detailed list of verbs, along with use cases, is available on MSDN:Â https://docs.microsoft.com/en-gb/powershell/developer/cmdlet/approved-verbs-for-windows-powershell-commands.
It is possible to use verbs other than the approved list. However, if a command using an unapproved verb is part of a module, a warning will be shown every time the module is imported.
A noun provides a very short description of the object the command is expecting to act on. The noun part may be a single word, as is the case with Get-Process
, New-Item
, or Get-Help
, or more than one word, as seen with Get-ChildItem
, Invoke-WebRequest
, or Send-MailMessage
.
The verb-noun pairing can make it a lot easier to find commands (without resorting to search engines).
For example, if we want to list firewall rules and we already know of the NetSecurity
module that's available in Windows PowerShell, we can run the following command, which shows the Get
commands in that module:
PS> Get-Command Get-*Firewall* -Module NetSecurity
CommandType Name Version Source
----------- ---- ------- ------
Function Get-NetFirewallAddressFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallApplicationFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallInterfaceFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallInterfaceTypeFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallPortFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallProfile 2.0.0.0 NetSecurity
Function Get-NetFirewallRule 2.0.0.0 NetSecurity
Function Get-NetFirewallSecurityFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallServiceFilter 2.0.0.0 NetSecurity
Function Get-NetFirewallSetting 2.0.0.0 NetSecurity
From the previous list, Get-NetFirewallRule
closely matches the requirement (to see a list of firewall rules) and should be explored.
Taking a broader approach, if the module was not known, we might still be able to guess by searching for commands containing specific nouns, for example, commands to get existing items that mention a firewall:
Get-Command Get-*Firewall*
Once a potential command has been found, Get-Help
can be used to assess whether or not the command is suitable.
Note
NetSecurity and PowerShell Core
The NetSecurity module is not available using PowerShell Core by default. Using modules such as NetSecurity in PowerShell Core is discussed in Chapter 2, Modules and Snap-ins.
An alias in PowerShell is an alternate name for a command. A command may have more than one alias.
The list of aliases may be viewed by using Get-Alias
, as shown in the following example:
PS> Get-Alias CommandType Name ----------- ---- Alias % -> ForEach-Object Alias ? -> Where-Object Alias ac -> Add-Content Alias asnp -> Add-PSSnapin Alias cat -> Get-Content Alias cd -> Set-Location
Get-Alias
may be used to find the command behind an alias:
Get-Alias dir
It can also be used to find the aliases for a command name:
Get-Alias -Definition Get-ChildItem
Examples of aliases that are frequently used in examples on the internet include the following:
%
forForEach-Object
?
forWhere-Object
cd
forSet-Location
gc
orcat
forGet-Content
ls
ordir
forGet-ChildItem
man
forhelp
(and thenGet-Help
)
An alias does not change how a command is used. There is no practical difference between the following two commands:
cd $env:TEMP
Set-Location $env:TEMP
New aliases are created with the New-Alias
command; for example, we might choose to create an alias named grep
for Select-String
:
New-Alias grep -Value Select-String
Each alias exists until the PowerShell session is closed.
As we saw while looking at syntax in Get-Help
, commands accept a mixture of parameters. The following sections show how these parameters are described in help and how to use them.
When viewing help for a command, we can see many different approaches to different parameters.
Optional parameters are surrounded by square brackets. This denotes an optional parameter that requires a value when used:
SYNTAX
Get-Process [-ComputerName <String[]>] ...
In this case, if a value for a parameter is to be specified, the name of the parameter must also be specified, as shown in the following example:
Get-Process -ComputerName somecomputer
It is not uncommon to see an optional positional parameter as the first parameter:
SYNTAX Get-Process [[-Name] <String[]>] ...
In this example, we may use either of the following:
Get-Process -Name powershell
Get-Process powershell
A mandatory parameter must always be supplied and is written as follows:
SYNTAX Get-ADUser -Filter <string> ...
In this case, the Filter
parameter name must be written and it must be given a value. For example, to supply a Filter
for the command, the Filter
parameter must be explicitly written:
Get-ADUser -Filter 'sAMAccountName -eq "SomeName"'
Parameters that are mandatory and accept values based on position are written as follows:
SYNTAX Get-ADUser [-Identity] <ADUser> ...
In this case, the Identity
parameter name is optional but the value is not. This command may be used as described by either of the following examples:
Get-ADUser -Identity useridentity
Get-ADUser useridentity
In both cases, the supplied value fills the Identity
parameter. A command with more than one mandatory positional parameter may appear as follows:
SYNTAX Add-Member [-NotePropertyName] <String> [-NotePropertyValue] <Object> ...
In this case, the command may be called as follows:
Add-Member -NotePropertyName Name -NotePropertyValue "value"
Add-Member -NotePropertyValue "value" -NotePropertyName Name
Add-Member Name -NotePropertyValue "value"
Add-Member Name "value"
Switch parameters have no arguments (values); the presence of a switch parameter is sufficient. For example, Recurse
is a switch parameter for Get-ChildItem
:
SYNTAX Get-ChildItem ... [-Recurse] ...
As with the other types of parameters, optional use is denoted by square brackets. Switch parameters, by default, are false
(not set). If a switch parameter is true
(set) by default, it is possible to set the value to false
using the notation, as shown in the following code:
Get-ChildItem -Recurse:$false
In the case of Get-ChildItem
, this does nothing; this technique is most widely used with the Confirm
switch parameter, which we will discuss later in this chapter.
When looking at the syntax, you will see that most commands end with a CommonParameters
item:
SYNTAX Get-Process ... [<CommonParameters>]
These common parameters are documented inside PowerShell:
Get-Help about_CommonParameters
These parameters let you control some of the standardized functionality PowerShell provides, such as verbose output and actions to take when errors occur.
For example, Stop-Process
does not explicitly state that it has a Verbose
parameter, but as Verbose
is a common parameter it may be used. This can be seen if notepad
is started and immediately stopped:
PS> Start-Process notepad -Verbose -PassThru | Stop-Process -Verbose VERBOSE: Performing the operation "Stop-Process" on target "notepad (5592)".
Value types of arguments (the type of value expected by a parameter) are enclosed in angular brackets, as shown in the following example:
<string> <string[]>
If a value is in the <string>
form, a single value is expected. If the value is in the <string[]>
form, an array (or list) of values is expected.
For example, Get-CimInstance
accepts a single value only for the ClassName
parameter:
SYNTAX Get-CimInstance [-ClassName] <String> ...
The command may be called as follows:
Get-CimInstance -ClassName Win32_OperatingSystem
In comparison, Get-Process
accepts multiple values for the Name
parameter:
SYNTAX Get-Process [[-Name] <String[]>] ...
Get-Process
may be called as follows:
Get-Process -Name powershell, explorer, smss
Many of the commands in PowerShell have more than one parameter set. This was seen while looking at the syntax section of help; for example, Stop-Process
has three parameter sets:
SYNTAX Stop-Process [-Id] <Int32[]> [-Confirm] [-Force] [-PassThru] [-WhatIf] [<CommonParameters>] Stop-Process [-InputObject] <Process[]> [-Confirm] [-Force] [-PassThru] [-WhatIf] [<CommonParameters>] Stop-Process [-Confirm] [-Force] -Name <String[]> [-PassThru] [-WhatIf] [<CommonParameters>]
Each parameter set must have one or more parameters unique to that set. This allows each set to be distinguished from the other. In the previous example, Id
, InputObject
, and Name
are used as differentiators.
The first parameter set expects a process ID, and this ID may be supplied with the parameter name or based on position; for example, both of these commands close the current PowerShell console:
Stop-Process -Id $PID
Stop-Process $PID
The second parameter set needs a value for InputObject
. Again, this may be supplied as a positional parameter. In this case, it will be distinguished based on its type:
$process = Start-Process notepad -PassThru
Stop-Process -InputObject $process
Stop-Process $process
$process | Stop-Process
Note
Pipeline input
Get-Help
should help show which parameters accept pipeline input, and examples are likely to show how.
If Get-Help
is incomplete, Get-Command
can be used to explore parameters:(Get-Command Stop-Process).Parameters.InputObject.Attributes
.
Â
The Confirm
, WhatIf
, and Force
parameters are used with commands that make changes (to files, variables, data, and so on). These parameters are often used with commands that use the verbs Set
or Remove
, but the parameters are not limited to specific verbs.
Confirm
and WhatIf
have associated preference variables. Preference
variables have an about
file, which may be viewed using the following command:
Get-Help about_Preference_Variables
The Force
parameter is not one of PowerShell's common parameters, that is, parameters that are automatically added by PowerShell itself.
Force is often seen in commands that might otherwise prompt for confirmation. There is no fixed use of the Force
parameter. The effect of using Force
is a choice a command developer must make. The Help
documentation should state the effect of using Force
, as is the case with the Remove-Item
command in the following example:
Get-Help Remove-Item -Parameter Force
The Confirm
parameter causes a command to prompt before an action is taken; for example, the Confirm
parameter forces Remove-Item
to prompt when a file is to be removed:
PS> Set-Location $env:TEMP PS> New-Item IMadeThisUp.txt -Force PS> Remove-Item .\IMadeThisUp.txt -Confirm Confirm Are you sure you want to perform this action? Performing the operation "Remove File" on target "C:\Users\whoami\AppData\Local\Temp\IMadeThisUp.txt". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
We have seen that a confirmation prompt may be forcefully requested in the previous example. In a similar manner, confirmation prompts may be suppressed; for example, the value of the Confirm
parameter may be explicitly set to false
, as shown in the following code:
Remove-Item .\IMadeThisUp.txt -Confirm:$false
Note
There is more than one way of prompting
There are two ways of requesting confirmation in PowerShell: Confirm
and the associated ConfirmPreference
; the variable only acts against one of these.
Using the parameter or changing the variable will not suppress all prompts. For example, Remove-Item
will always prompt if you attempt to delete a directory that is not empty without supplying the Recurse
parameter.
This technique is useful for commands that prompt by default; for example, Clear-RecycleBin
will prompt by default:
PS> Clear-RecycleBin Confirm Are you sure you want to perform this action? Performing the operation "Clear-RecycleBin" on target " All of the contents of the Recycle Bin". [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):
Setting the Confirm
parameter to false
for Clear-RecycleBin
will bypass the prompt and immediately empty the recycle bin:
Clear-RecycleBin -Confirm:$false
Note
Finding commands with a specific impact
The following snippet will return a list of all commands that state they have a high impact:Get-Command -CommandType Cmdlet, Function | Where-Object {
  $metadata = New-Object System.Management.Automation.CommandMetadata($_)
  $metadata.ConfirmImpact -eq 'High'
}
If the Confirm
parameter is not set, whether or not a prompt is shown is determined by PowerShell. The value of the ConfirmPreference
variable is compared with the stated impact of a command.
By default, the value of ConfirmPreference
is High
, as shown in the following code:
PS> $ConfirmPreference
High
By default, commands have a medium impact.
Note
Finding ConfirmImpact
In scripts and functions, the ConfirmImpact
setting is part of the CmdletBinding
attribute: [CmdletBinding(ConfirmImpact = 'High')]
.
If CmdletBinding
or ConfirmImpact
are not present, the impact is medium.
The impact of a function or cmdlet
may be viewed using the ConfirmImpact
property of a command's metadata:New-Object System.Management.Automation.CommandMetadata(Get-Command Remove-Item)
.
ConfirmPreference
has four possible values:
High
: Prompts when command impact isHigh
(default)Medium
: Prompts when command impact isMedium
orHigh
Low
: Prompts when command impact isLow
,Medium
, orHigh
None
: Never prompts
A new value may be set by assigning it in the console; for example, it can be set to Low
:
$ConfirmPreference = 'Low'
Note
ConfirmPreference and the Confirm parameter
While ConfirmPreference
may be set to None
to suppress confirmation prompts, confirmation may still be explicitly requested. Let's look at an example:$ConfirmPreference = 'None'
New-Item NewFile.txt -Confirm
Since the Confirm
parameter is supplied, the ConfirmPreference
value within the scope of the command (New-Item
) is Low
, and therefore the prompt displays.
Â
The WhatIf
parameter replaces the confirmation prompt with a simple statement that should state what would have been done, using Remove-Item
as an example again:
PS> Set-Location $env:TEMP PS> New-Item IMadeThisUp.txt -Force PS> Remove-Item .\IMadeThisUp.txt -WhatIf Confirm Are you sure you want to perform this action? What If: Performing the operation "Remove File" on target "C:\Users\whoami\AppData\Local\Temp\IMadeThisUp.txt".
If both Confirm
and WhatIf
are used with a command, WhatIf
takes precedence.
WhatIf
may be unset on a per-command basis by supplying a value of false
in the same manner as the Confirm
parameter. Let's look at the following example:
'Some message' | Out-File $env:TEMP\test.txt -WhatIf:$false
The previous technique can be useful if a file (such as a log file) should be written to, irrespective of whether WhatIf
is being used or not.
The WhatIfPreference
variable holds a Boolean value (true
orfalse
) and has a default value offalse
.
If the preference variable is set to true
, all commands that support WhatIf
will act as if the parameter is explicitly set. A new value may be set for the variable, as shown in the following code:
$WhatIfPreference = $true
The WhatIf
preference variable takes precedence over the Confirm
parameter. For example, the WhatIf
dialog will be shown when running the followingNew-Item
, but the Confirm
prompt will not:
$WhatIfPreference = $true
New-Item NewFile.txt -Confirm
The Force
parameter has a different purpose. With the Force
parameter, New-Item
will overwrite any existing file with the same path. When used with Remove-Item
, the Force
parameter allows the removal of files with Hidden
or System
attributes. The error that's generated when attempting to delete a Hidden
file is shown in the following code:
PS> Set-Location $env:TEMP PS> New-Item IMadeThisUp.txt -Force PS> Set-ItemProperty .\IMadeThisUp.txt âName Attributes âValue Hidden PS> Remove-Item IMadeThisUp.txt Remove-Item : Cannot remove item C:\Users\whoami\AppData\Local\Temp\IMadeThisUp.txt: You do not have sufficient access rights to perform this operation. At line:1 char:1 + Remove-Item .\IMadeThisUp.txt + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (C:\Users\uktpcd...IMadeThisUp.txt:FileInfo) [Remove-Item], IOException + FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
Adding the Force
parameter allows the operation to continue without the error message:
Set-Location $env:TEMP New-Item IMadeThisUp.txt -Force Set-ItemProperty .\IMadeThisUp.txt âName Attributes âValue Hidden Remove-Item IMadeThisUp.txt -Force
Providers in PowerShell present access to data that is not normally easily accessible. There are providers for the filesystem, registry, certificate store, and so on. Each provider arranges data so that it resembles a filesystem.
Note
PowerShell Core: What happened to provider help?
PowerShell Core does not include Provider help files. Help may be viewed either online or in Windows PowerShell.
A longer description of Providers
may be seen by viewing the about
file:
Get-Help about_Providers
The list of providers available in the current PowerShell session may be viewed by running Get-PSProvider
, as shown in the following example:
PS> Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C, D}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
Certificate ShouldProcess {Cert}
WSMan Credentials {WSMan}
Each of the previous providers has a help file associated with it. These can be accessed using the following code:
Get-Help -Name <ProviderName> -Category Provider
For example, the help file for the certificate provider may be viewed by running the following code:
Get-Help -Name Certificate -Category Provider
A list of all help files for providers may be seen by running the following code:
Get-Help -Category Provider
The output from Get-PSProvider
shows that each provider has one or more drives associated with it.
Alternatively, you can see the list of drives (and the associated provider) using Get-PSDrive
, as shown in the following code:
PS> Get-PSDrive
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
Alias Alias
C 89.13 89.13 111.64 FileSystem C:\
Cert Certificate \
D 0.45 21.86 FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
WSMan WSMan
As providers are presented as a filesystem, accessing a provider is similar to working with a drive. This example shows how Get-ChildItem
changes when exploring the Cert
drive:
PS C:\> Set-Location Cert:\LocalMachine\Root PS Cert:\LocalMachine\Root> Get-ChildItem Directory: Microsoft.PowerShell.Security\Certificate::LocalMachine\Root Thumbprint Subject ---------- ------- CDD4EEAE6000AC7F40C3802C171E30148030C072 CN=Microsoft Root Certif... BE36A4562FB2EE05DBB3D32323ADF445084ED656 CN=Thawte Timestamping C... A43489159A520F0D93D032CCAF37E7FE20A8B419 CN=Microsoft Root Author...
A similar approach may be taken to access the registry. By default, drives are available for the current user HKCU
 and local machine HKLM
 hives. Accessing HKEY_USERS
is possible by adding a new drive with the following command:
New-PSDrive HKU -PSProvider Registry -Root HKEY_USERS
After running the preceding command, a new drive may be used:
PS C:\> Get-ChildItem HKU:
Hive: HKEY_USERS
Name Property
---- --------
.DEFAULT
S-1-5-19
S-1-5-20
Note
Running HKCU or Cert: does not change the drive
Running C:
or D:
in the PowerShell console changes to a new drive letter. This is possible because C:
is a function that calls Set-Location
: (Get-Command C:).Definition
.
Every letter of the alphabet (A to Z) has a predefined function (Get-Command*:
) but the other drives (for example, Cert
, HKCU
, and so on) do not. Set-Location
(or its alias cd
) must be used to switch into these drives.
As we saw previously, providers may be accessed in the same way as the filesystem. Commands we might traditionally think of as filesystem commands (such as Get-ChildItem
, New
 and Remove-Item
, Get
and Set-Acl
, and Get
and Set-ItemProperty
) can work with data presented by a provider.
The list of parameters for the filesystem commands changes depending on the provider. The affected parameters are detailed in the help files for individual providers.
If we look at the FileSystem
provider help file (Get-Help FileSystem
), we can see that Get-ChildItem
has a file switch parameter that can be used to filter files only:
-File <System.Management.Automation.SwitchParameter> Gets files. The File parameter was introduced in Windows PowerShell 3.0. To get only files, use the File parameter and omit the Directory parameter. To exclude files, use the Directory parameter and omit the File parameter, or use the Attributes parameter. Cmdlets Supported: Get-ChildItem
Let's look at the following example:
Set-Location C:
Get-ChildItem -File
Looking at the Certificate provider
help file (Get-Help Certificate
), a different set of parameters is available.
Note
PowerShell Core: The certificate provider
The parameters shown next have been removed from PowerShell Core but may return in time. In the meantime, the examples here are valid for Windows PowerShell.
For example, this excerpt shows the ExpiringInDays
parameter for Get-ChildItem
:
-ExpiringInDays <System.Int32> Gets certificates that are expiring in or before the specified number of days. Enter an integer. A value of 0 (zero) gets certificates that have expired. This parameter is valid in all subdirectories of the Certificate provider, but it is effective only on certificates. This parameter was introduced in Windows PowerShell 3.0. Cmdlets Supported: Get-ChildItem
The previous parameter may be used to find the Root
certificates expiring in the next two years, as shown in the following example:
Get-ChildItem Cert:\LocalMachine\Root -ExpiringInDays 730
Splatting is a technique that was introduced all the way back in PowerShell 2. Splatting is a way of defining the parameters of a command before calling the command. This is an important and often underrated technique.
Individual parameters are written in a hashtable (@{}
), and then the @
symbol is used to tell PowerShell that the content of the hashtable should be read as parameters.
This example supplies the Name
parameter for the Get-Process
command, and is normally written as Get-Process -Name explorer
:
$getProcess = @{ Name = 'explorer' } Get-Process @getProcess
In this example, getProcess
is used as the name of the variable for the hashtable. The name is arbitrary; any variable name can be used.
Splatting may be used with cmdlets, functions, and scripts. Splatting may be used when the call operator is present, for example:
$getProcess = @{ Name = 'explorer' } & 'Get-Process' @getProcess
The benefit of splatting is most obvious when working with commands that expect a larger number of parameters.
This first example uses the Windows PowerShell module ScheduledTasks
to create a fairly basic task that runs once a day at midnight:
$taskAction = New-ScheduledTaskAction -Execute pwsh.exe -Argument 'Write-Host "hello world"' $taskTrigger = New-ScheduledTaskTrigger -Daily -At '00:00:00' Register-ScheduledTask -TaskName 'TaskName' -Action $taskAction -Trigger $taskTrigger -RunLevel 'Limited' -Description 'This line is too long to read'
It is possible to spread the command out, in an attempt to make it easier to read, by escaping the end-of-line character, for example:
$taskAction = New-ScheduledTaskAction -Execute pwsh.exe ` -Argument 'Write-Host "hello world"' $taskTrigger = New-ScheduledTaskTrigger -Daily ` -At '00:00:00' Register-ScheduledTask -TaskName 'TaskName' ` -Action $taskAction ` -Trigger $taskTrigger ` -RunLevel 'Limited' ` -Description 'This line is too long to read'
The approach that's used here is relatively common, but it is fragile. It is easy to miss a tick from the end-of-line, or to accidentally add a space after a tick character. Both will break continuation, and the command will still execute but with an incomplete set of parameters; afterwards, an error may be displayed, or a prompt may be shown, depending on the parameter (or parameters) it missed.
This problem is shown in the following screenshot, where a space character has been accidentally included after the Daily
switch parameter:

Splatting provides a neater, generally easier to read and more robust alternative. The following example shows one possible way to tackle these commands when using splatting:
$newTaskAction = @{ Execute = 'pwsh.exe' Argument = 'Write-Host "hello world"' } $newTaskTrigger = @{ Daily = $true At = '00:00:00' } $registerTask = @{ TaskName = 'TaskName' Action = New-ScheduledTaskAction @newTaskAction Trigger = New-ScheduledTaskTrigger @newTaskTrigger RunLevel = 'Limited' Description = 'Splatting is easy to read' } Register-ScheduledTask @registerTask
Splatting may be used to avoid repetition when a parameter must be optionally passed on to a number of different commands. It is possible to splat more than one set of parameters.
In this example, the ComputerName
and Credential
parameters are used by two different commands:
# Parameters used to authenticate remote connections $remoteParams = @{ Credential = Get-Credential ComputerName = $env:COMPUTERNAME } # Parameters which are specific to Test-WSMan $testWSMan = @{ Authentication = 'Default' ErrorAction = 'SilentlyContinue' } # By default, do not pass any extra parameters to New-CimSession $newCimSession = @{} if (-not (Test-WSMan @testWSMan @remoteParams)) { # If WSMan fails, use DCOM (RPC over TCP) to connect $newCimSession.Add('SessionOption', (New-CimSessionOption -Protocol Dcom)) } # Parameters to pass to Get-CimInstance $getCimInstance = @{ ClassName = 'Win32_Service' CimSession = New-CimSession @newCimSession @remoteParams } Get-CimInstance @getCimInstance
This example takes advantage of a number of features:
- It is possible to splat no parameters using an empty hashtable (
@{}
) - It is possible to test conditions and dynamically add parameters at run time (if needed)
- It is possible to splat more than one set of parameters into a command
As the preceding example shows, it is possible to dynamically choose the parameters that are passed to a command without having to write the command in full more than once in a script.
So far, all of the parameters that have been used were given were names. It is possible, although rare, to splat positional parameters. This will be demonstrated using the Rename-Item
command, which has two positional parameters: path and new name. It is possible to run Rename-Item
as follows:
Rename-Item oldname.txt newname.txt
An array may be used to splat these positional parameters:
$renameItem = 'oldname.txt', 'newname.txt' Rename-Item @renameItem
In this chapter, we explored the help system that's built into PowerShell. We took a brief look at syntax, examples, and parameters. We also looked at how help content may be moved between computers.
Command naming and discovery introduced how we might use the verb-noun pairing to discover commands that can be used. Aliases were introduced briefly.
Parameters and parameter sets were explored, as well as different types of parameters.
We took a basic look at providers and how they are used before taking a look at handling long command lines using splatting.
In Chapter 2, Modules and Snap-ins, we will explore the commands that are used to find, install, and load modules in PowerShell.