Chapter 5 - Formatting, aliases, providers, comparison
Requirements
The SQL Server PowerShell module is required by some of the examples shown in this chapter. The module installs as part of SQL Server Management Studio (SSMS). It's also used in subsequent chapters. Download and install it on your Windows 10 lab environment computer.
Format Right
In Chapter 4, you learned to filter as far to the left as possible. The rule for manually formatting a command's output is similar to that rule except it needs to occur as far to the right as possible.
The most common format commands are Format-Table
and Format-List
. Format-Wide
and
Format-Custom
can also be used, but are less common.
As mentioned in Chapter 3, a command that returns more than four properties defaults to a list unless custom formatting is used.
Get-Service -Name w32time | Select-Object -Property Status, DisplayName, Can*
Status : Running
DisplayName : Windows Time
CanPauseAndContinue : False
CanShutdown : True
CanStop : True
Use the Format-Table
cmdlet to manually override the formatting and show the output in a table
instead of a list.
Get-Service -Name w32time | Select-Object -Property Status, DisplayName, Can* |
Format-Table
Status DisplayName CanPauseAndContinue CanShutdown CanStop
------ ----------- ------------------- ----------- -------
Running Windows Time False True True
The default output for Get-Service
is three properties in a table.
Get-Service -Name w32time
Status Name DisplayName
------ ---- -----------
Running w32time Windows Time
Use the Format-List
cmdlet to override the default formatting and return the results in a list.
Get-Service -Name w32time | Format-List
Name : w32time
DisplayName : Windows Time
Status : Running
DependentServices : {}
ServicesDependedOn : {}
CanPauseAndContinue : False
CanShutdown : True
CanStop : True
ServiceType : Win32ShareProcess
Notice that simply piping Get-Service
to Format-List
made it return additional properties. This
doesn't occur with every command because of the way the formatting for that particular command is
set up behind the scenes.
The number one thing to be aware of with the format cmdlets is they produce format objects that are different than normal objects in PowerShell.
Get-Service -Name w32time | Format-List | Get-Member
TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
autosizeInfo Property Microsoft.PowerShell.Commands.Inter...
ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c9...
groupingEntry Property Microsoft.PowerShell.Commands.Inter...
pageFooterEntry Property Microsoft.PowerShell.Commands.Inter...
pageHeaderEntry Property Microsoft.PowerShell.Commands.Inter...
shapeInfo Property Microsoft.PowerShell.Commands.Inter...
TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c9...
groupingEntry Property Microsoft.PowerShell.Commands.Inter...
shapeInfo Property Microsoft.PowerShell.Commands.Inter...
TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c9...
formatEntryInfo Property Microsoft.PowerShell.Commands.Inter...
outOfBand Property bool outOfBand {get;set;}
writeStream Property Microsoft.PowerShell.Commands.Inter...
TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c9...
groupingEntry Property Microsoft.PowerShell.Commands.Inter...
TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
ClassId2e4f51ef21dd47e99d3c952918aff9cd Property string ClassId2e4f51ef21dd47e99d3c9...
groupingEntry Property Microsoft.PowerShell.Commands.Inter...
What this means is format commands can't be piped to most other commands. They can be piped to some
of the Out-*
commands, but that's about it. This is why you want to perform any formatting at the
very end of the line (format right).
Aliases
An alias in PowerShell is a shorter name for a command. PowerShell includes a set of built-in aliases and you can also define your own aliases.
The Get-Alias
cmdlet is used to find aliases. If you already know the alias for a command, the
Name parameter is used to determine what command the alias is associated with.
Get-Alias -Name gcm
CommandType Name Version Source
----------- ---- ------- ------
Alias gcm -> Get-Command
Multiple aliases can be specified for the value of the Name parameter.
Get-Alias -Name gcm, gm
CommandType Name Version Source
----------- ---- ------- ------
Alias gcm -> Get-Command
Alias gm -> Get-Member
You'll often see the Name parameter omitted since it's a positional parameter.
Get-Alias gm
CommandType Name Version Source
----------- ---- ------- ------
Alias gm -> Get-Member
If you want to find aliases for a command, you'll need to use the Definition parameter.
Get-Alias -Definition Get-Command, Get-Member
CommandType Name Version Source
----------- ---- ------- ------
Alias gcm -> Get-Command
Alias gm -> Get-Member
The Definition parameter can't be used positionally so it must be specified.
Aliases can save you a few keystrokes and they're fine when you're typing commands into the console. They shouldn't be used in scripts or any code that you're saving or sharing with others. As mentioned earlier in this book, using full cmdlet and parameter names is self-documenting and easier to understand.
Use caution when creating your own aliases because they'll only exist in your current PowerShell session on your computer.
Providers
A provider in PowerShell is an interface that allows file system like access to a datastore. There are a number of built-in providers in PowerShell.
Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C, A, D}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
Certificate ShouldProcess {Cert}
WSMan Credentials {WSMan}
As you can see in the previous results, there are built-in providers for the registry, aliases, environment variables, the file system, functions, variables, certificates, and WSMan.
The actual drives that these providers use to expose their datastore can be determined with the
Get-PSDrive
cmdlet. The Get-PSDrive
cmdlet not only displays drives exposed by providers, but it
also displays Windows logical drives including drives mapped to network shares.
Get-PSDrive
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
A FileSystem A:\
Alias Alias
C 14.41 112.10 FileSystem C:\
Cert Certificate \
D FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
Variable Variable
WSMan WSMan
Third-party modules such as the Active Directory PowerShell module and the SQLServer PowerShell module both add their own PowerShell provider and PSDrive.
Import the Active Directory and SQL Server PowerShell modules.
Import-Module -Name ActiveDirectory, SQLServer
Check to see if any additional PowerShell providers were added.
Get-PSProvider
Name Capabilities Drives
---- ------------ ------
Registry ShouldProcess, Transactions {HKLM, HKCU}
Alias ShouldProcess {Alias}
Environment ShouldProcess {Env}
FileSystem Filter, ShouldProcess, Credentials {C, A, D}
Function ShouldProcess {Function}
Variable ShouldProcess {Variable}
ActiveDirectory Include, Exclude, Filter, Shoul... {AD}
SqlServer Credentials {SQLSERVER}
Notice that in the previous set of results, two new PowerShell providers now exist, one for Active Directory and another one for SQL Server.
A PSDrive for each of those modules was also added.
Get-PSDrive
Name Used (GB) Free (GB) Provider Root
---- --------- --------- -------- ----
A FileSystem A:\
AD ActiveDire... //RootDSE/
Alias Alias
C 19.38 107.13 FileSystem C:\
Cert Certificate \
D FileSystem D:\
Env Environment
Function Function
HKCU Registry HKEY_CURRENT_USER
HKLM Registry HKEY_LOCAL_MACHINE
SQLSERVER SqlServer SQLSERVER:\
Variable Variable
WSMan WSMan
PSDrives can be accessed just like a traditional file system.
Get-ChildItem -Path Cert:\LocalMachine\CA
PSParentPath: Microsoft.PowerShell.Security\Certificate::LocalMachine\CA
Thumbprint Subject
---------- -------
FEE449EE0E3965A5246F000E87FDE2A065FD89D4 CN=Root Agency
D559A586669B08F46A30A133F8A9ED3D038E2EA8 OU=www.verisign.com/CPS Incorporated LIABI...
109F1CAED645BB78B3EA2B94C0697C740733031C CN=Microsoft Windows Hardware Compatibility,...
Comparison Operators
PowerShell contains a number of comparison operators that are used to compare values or find values that match certain patterns. Table 5-1 contains a list of comparison operators in PowerShell.
Operator | Definition |
---|---|
-eq |
Equal to |
-ne |
Not equal to |
-gt |
Greater than |
-ge |
Greater than or equal to |
-lt |
Less than |
-le |
Less than or equal to |
-Like |
Match using the * wildcard character |
-NotLike |
Does not match using the * wildcard character |
-Match |
Matches the specified regular expression |
-NotMatch |
Does not match the specified regular expression |
-Contains |
Determines if a collection contains a specified value |
-NotContains |
Determines if a collection does not contain a specific value |
-In |
Determines if a specified value is in a collection |
-NotIn |
Determines if a specified value is not in a collection |
-Replace |
Replaces the specified value |
All of the operators listed in Table 5-1 are case-insensitive. Place a c
in front of the operator
listed in Table 5-1 to make it case-sensitive. For example, -ceq
is the case-sensitive version of
the -eq
comparison operator.
Proper case "PowerShell" is equal to lower case "powershell" using the equals comparison operator.
'PowerShell' -eq 'powershell'
True
It's not equal using the case-sensitive version of the equals comparison operator.
'PowerShell' -ceq 'powershell'
False
The not equal comparison operator reverses the condition.
'PowerShell' -ne 'powershell'
False
Greater than, greater than or equal to, less than, and less than or equal all work with string or numeric values.
5 -gt 5
False
Using greater than or equal to instead of greater than with the previous example returns the Boolean true since five is equal to five.
5 -ge 5
True
Based on the results from the previous two examples, you can probably guess how both less than and less than or equal to work.
5 -lt 10
True
The -Like
and -Match
operators can be confusing, even for experienced PowerShell users. -Like
is used with wildcard the characters *
and ?
to perform "like" matches.
'PowerShell' -like '*shell'
True
-Match
uses a regular expression to perform the matching.
'PowerShell' -match '^*.shell$'
True
Use the range operator to store the numbers 1 through 10 in a variable.
$Numbers = 1..10
Determine if the $Numbers
variable includes 15.
$Numbers -contains 15
False
Determine if it includes the number 10.
$Numbers -contains 10
True
-NotContains
reverses the logic to see if the $Numbers
variable doesn't contain a value.
$Numbers -notcontains 15
True
The previous example returns the Boolean true because it's true that the $Numbers
variable
doesn't contain 15. It does however contain the number 10 so it's false when it's tested.
$Numbers -notcontains 10
False
The "in" comparison operator was first introduced in PowerShell version 3.0. It's used to determine
if a value is "in" an array. The $Numbers
variable is an array since it contains multiple values.
15 -in $Numbers
False
In other words, -in
performs the same test as the contains comparison operator except from the
opposite direction.
10 -in $Numbers
True
15 isn't in the $Numbers
array so false is returned in the following example.
15 -in $Numbers
False
Just like the -contains
operator, not
reverses the logic for the -in
operator.
10 -notin $Numbers
False
The previous example returns false because the $Numbers
array does include 10 and the condition
was testing to determine if it didn't contain 10.
15 is "not in" the $Numbers
array so it returns the Boolean true.
15 -notin $Numbers
True
The -replace
operator does just want you would think. It's used to replace something. Specifying
one value replaces that value with nothing. In the following example, I replace "Shell" with nothing.
'PowerShell' -replace 'Shell'
Power
If you want to replace a value with a different value, specify the new value after the pattern you want to replace. SQL Saturday in Baton Rouge is an event that I try to speak at every year. In the following example, I replace the word "Saturday" with the abbreviation "Sat".
'SQL Saturday - Baton Rouge' -Replace 'saturday','Sat'
SQL Sat - Baton Rouge
There are also methods like Replace() that can be used to replace things similar to the way the
replace operator works. However, the -Replace
operator is case-insensitive by default, and the
Replace() method is case-sensitive.
'SQL Saturday - Baton Rouge'.Replace('saturday','Sat')
SQL Saturday - Baton Rouge
Notice that the word "Saturday" wasn't replaced in the previous example. This is because it was specified in a different case than the original. When the word "Saturday" is specified in the same case as the original, the Replace() method does replace it as expected.
'SQL Saturday - Baton Rouge'.Replace('Saturday','Sat')
SQL Sat - Baton Rouge
Be careful when using methods to transform data because you can run into unforeseen problems, such as failing the Turkey Test. For an example, see the blog article titled Using Pester to Test PowerShell Code with Other Cultures. My recommendation is to use an operator instead of a method whenever possible to avoid these types of problems.
While the comparison operators can be used as shown in the previous examples, I normally find myself
using them with the Where-Object
cmdlet to perform some type of filtering.
Summary
In this chapter, you've learned a number of different topics to include Formatting Right, Aliases, Providers, and Comparison Operators.
Review
- Why is it necessary to perform Formatting as far to the right as possible?
- How do you determine what the actual cmdlet is for the
%
alias? - Why shouldn't you use aliases in scripts you save or code you share with others?
- Perform a directory listing on the drives that are associated with one of the registry providers.
- What's one of the main benefits of using the replace operator instead of the replace method?
Recommended Reading
Feedback
https://aka.ms/ContentUserFeedback.
Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see:Submit and view feedback for