Many tech pros put up with repetitive tasks and manage things via the point-and-click method when they could save so much time by automating things. PowerShell, the shell and scripting language by Microsoft, can help. What is PowerShell, anyway?
In simplest forms, PowerShell is a cross-platform shell and scripting language that allows people to manage tasks from the command line and automate thousands of activities. It’s a language built on Microsoft’s .NET Framework that makes many of our lives easier.
In this article, you’re going to learn about PowerShell, where it came from, PowerShell basics, and help you understand why PowerShell might be the right tool to use.
We have hundreds of blog posts on PowerShell. If you’re new to this language, check out all of the other posts we have here.
What is PowerShell?
PowerShell is an open source shell and scripting language built on top of Microsoft .NET technology. It aims to help tech pros that may not be software developers build efficient scripts and tools to help them do their job better.
Evolving from languages like VBScript and batch files, PowerShell was designed to provide a first-class command-line interface and script language that’s easy to understand and use.
PowerShell is object-oriented and heavily depends on objects similar to object-oriented programming (OOP). Just about everything in PowerShell is an object you’ll soon learn more about.
PowerShell is two things; it’s a command-line shell that allows users to run commands at a command-line similar to the legacy command prompt (cmd.exe). It is also a robust scripting language that can build tools and automate just about anything you can think of.
Available to be run interactively or in a script, PowerShell offers many commands called cmdlets and functions. These commands are either compiled binaries or custom code written by the user to encapsulate a certain task like reading a file, pinging a remote computer, and so on.
The Evolution of PowerShell
In 2002, Jeffrey Snover of Microsoft realized that Windows did not have a good command-line interface and scripting ability like its competitor, Linux. To change this, Snover released the Monad Manifesto, a document outlining his plans for what would eventually be PowerShell.
From 2002-2005, PowerShell was called Monad and was still under early development. In 2006, the word ‘PowerShell’ made its debut with the release of PowerShell 1.0. From that point on, the PowerShell team at Microsoft has used the manifesto as a guide to add new features to PowerShell continually.
Originally only available as part of the Windows Management Framework, before Windows XP and Windows Server 2012, PowerShell was a separate install. But as of Windows 7 and Windows Server 2012 R2, PowerShell became installed by default on all Windows operating systems.
The Move to Cross Platform
From 2006 to 2016, PowerShell was only available on Windows, named Windows PowerShell up to version 5.1. PowerShell was built on top of the .NET Framework, which was only available in Windows. In 2016, Microsoft decided to make a bold move and open-source PowerShell on GitHub, where it dropped the ‘Windows’ and went to just ‘PowerShell’ in version six.
Since then, PowerShell has been available not just on Windows but on macOS, Linux, and other *nix operating systems where it uses .NET Core.
PowerShell/PowerShell Core is backward compatible Windows PowerShell. Both versions can be installed side by side.
The Future for PowerShell
As of 2021, PowerShell has already seen its greatest development efforts. Achieving what the Monad Manifesto set out to accomplish, the PowerShell team at Microsoft manages the product. Although most, if not all, of the ground-breaking features have already been released, Microsoft and the open-source community are still actively maintaining it.
Commands
Much like other shells like cmd.exe, Bash and others, PowerShell has binary commands to perform certain actions. For example, you can run a command to read a file, ping a computer, remove a registry key and a lot more.
PowerShell 7 is the most recent version, and it ships with more than 1500 compiled binaries called cmdlets. PowerShell cmdlets are ubiquitous and form the tools you can use to build complex scripts.
Unlike cmdlets that software developers build in other languages like C#, average Joes can create their own commands. Built-in the PowerShell language, functions allow those that know PowerShell to create commands similar to cmdlets.
Developers use these cmdlets and functions to build simple to complex solutions to automate anything you can think of.
Use the
Get-Command
cmdlet to discover all of the available commands on your system.
Command Syntax
One of the unique parts of PowerShell is the syntax. PowerShell has a syntax that reads as it executes for the IT professional.
Unlike other shells, the commands follow a standard naming convention indicating exactly what the command’s purpose is.
Named in a Verb-Noun syntax, command names always start with a verb, followed by a dash and a noun.
Although PowerShell doesn’t require you to use the Verb-Noun syntax for your custom functions, Microsoft highly encourages it.
Verbs
The most important part of a cmdlet name is the verb. This part should accurately describe what action the cmdlet performs. For example, Get-Content
gets text from a file while Copy-Item
copies a file. You can even find all “approved” verbs by running the Get-Verb
command in a PowerShell console, as shown below.
Nouns
Unlike verbs, PowerShell doesn’t have any “approved” nouns. The object on which an action is taken on can vary wildly. But, PowerShell does separate a verb from a noun inside of the engine. You can see an example of this by running the Get-Command
command using the Noun
parameter.
By specifying the Noun
parameter and providing a value of A*
. PowerShell will “split” all of its available commands into a verb and a noun and only show you commands with a noun that starts with A.
Modules
In the previous section, you saw the output of the Get-Command
command. In that output, you could see a column called Source
. To compartmentalize commands, PowerShell requires all cmdlets to be part of a “bucket” or module.
Modules are groups of commands combined based on a common function. For example, many core PowerShell cmdlets are in a module called Microsoft.PowerShell.Management while cmdlets like Write-Host
and Write-Debug
are in the Microsoft.PowerShell.Utility module.
PowerShell comes with a few dozen modules pre-installed, but you can also download thousands of other modules based on a task or product. You can find modules to manage other vendor products or even create your own.
You can find all modules installed on your computer by running Get-Module -ListAvailable
. The Get-Module
command finds all of the modules that have been loaded (imported into your current session). The ListAvailable
parameter tells Get-Module
to also search for modules installed on your file system but not imported.
Use the
Find-Module
command to search the PowerShell Gallery to discover thousands of other modules.
Objects
Once you get comfortable with PowerShell, one of the most important aspects you need to learn is objects. Everything in PowerShell is an object with properties and methods.
To understand PowerShell, you must first understand how objects work.
Real World Objects
Think of a single real-world “object”. Let’s work with a cat. A cat is a thing with various attributes (properties) like color, size, age, etc that define the cat’s characteristics.
Each cat is an object with certain attributes that describe it. Those attributes are properties.
Now, a cat isn’t some immovable object. It does something like running, jumping, blinking its eyes, or purring. A cat (object) performs some action. In PowerShell, the cat object has various methods which take action to do something.
Object Types
Using the cat examples from above, every cat is a cat. But a dog is an object too. We now have two types of objects. In programming, those different objects are called types. A type is a specific kind of object with a common set of properties and methods.
A cat is a type, a dog is a type, and a car is a type. Each object has a specific set of attributes and actions it can perform.
Object Properties and Methods
If a cat can be thought of as an object with properties and methods, how do you represent that in code? To explain that, let’s first start with a common type of object, a string.
If you type the below text into your console and hit Enter, it will return the value back to you but more is happening in the background.
"This is a Plain Text, and its an object"
When you hit Enter on your keyboard, PowerShell creates an object, specifically an object with a type of System.String. This string object has various “members,” which is PowerShell’s term for all properties and methods.
You can see all of the members assigned to this string object by piping (more on that later) the string’s output to the Get-Member
cmdlet. The Get-Member
cmdlet is a handy command that inspects PowerShell objects.
Length
is one property of a string that indicates how long the string is. You can reference the value of a property using dot notation, as shown below.
"This is a Plain Text, and its an object".Length
You can see that PowerShell returns a value of 39
, indicating this script is 39 character problems.
You’d reference a method on an object in a similar fashion. But, instead of just a set of alphanumeric characters, methods require you to use parentheses.
Some methods have parameters. To pass those parameters to a method, you’d include them in the parentheses.
The string object has a method called Upper()
, which capitalizes all characters in the string, as shown below.
"This is a Plain Text, and its an object".ToUpper()
Read more about Get-Member, Properties and Methods on Microsoft.com website
PSDrives
One unique feature of this shell is the concept of a PSDrive. PowerShell drives or PSDrives, are “drives” you’re typically used to, like C:\ but with a twist. Your typical C:\ is a file system drive consisting of folders with files inside. A PSDrive can be that but can also be a registry hive, Active Directory, or certificate container.
PSDrives provide an abstraction from the actual data source and allow you to navigate multiple types of data hierarchically. Use the Get-PSDrive
cmdlet to find all available drives on your computer.
PowerShell has a set of cmdlets with a noun Item
, ChildItem
, and ItemProperty
. Each of these cmdlets that work with any PSDrive.
For example, to read a registry hive, you could run Get-ChildItem -Path HKLM:\
or perhaps you’d like to find a file’s attributes. To do that, you’d use Get-ItemProperty -Path C:\file.txt
.
Error Handling
Like all other programming languages, PowerShell also has error handling or exception handling support. Using .NET error handling like try
, catch
, and the legacy trap
commands, you can catch exceptions as they happen in your scripts.
Unlike other languages, though, PowerShell has a concept of hard and soft-terminating errors. A hard-terminating error is considered “worse” than a soft-terminating error. Depending on how the developer created the cmdlet, a cmdlet may return either a soft or hard-terminating error depending on various circumstances.
For example, perhaps you need to read a text file’s contents at C:\NonExistingFile.txt, and the file doesn’t exist. By default, Get-Content
returns a soft-terminating error if the file does not exist. Soft-terminating errors do not throw exceptions to the catch
block.
Soft-terminating errors simply return the error to the console and quit as shown below.
Try{
Get-Content -Path "C:\NonExistingFile.txt"
} Catch{
Write-Host "I Found An Error And Caught It.. " -ForegroundColor Yellow
}
All PowerShell cmdlets come with a parameter called ErrorAction
to override the default cmdlet behavior. Perhaps I want PowerShell to go into my catch
block when the file isn’t found. To do that, Get-Content
would need to return an exception or hard-terminating error.
To “convert” soft-terminating errors to hard-terminating errors for a cmdlet reference, use the Stop
value with the ErrorAction
parameter as shown below.
Try{
Get-Content -Path "C:\NonExistingFile.txt" -ErrorAction Stop
} Catch{
Write-Host "I Found An Error And Caught It.. " -ForegroundColor Yellow
}
The Pipeline
When you run a command in any shell, that command optionally returns the output. In Bash and other shell scripting languages, that output is a simple string. That string is not an object that doesn’t contain any other attributes, unlike PowerShell.
Since PowerShell returns only objects, it has a pipeline to support them. The concept of a pipeline is not unique but passing objects through it is.
For example, perhaps you have the Mozilla Firefox browser running which is running under a process called firefox. PowerShell has a built cmdlet called Get-Process
to discover running processes.
Get-Process firefox
PowerShell also has a cmdlet called Stop-Process
which stops running processes. In a traditional shell, you’d have to do something like this, taking up two lines and extra complexity.
$process = Get-Process firefox
Stop-Process $process
But, since the Stop-Process
cmdlet accepts input via the pipeline, it has the logic to understand the process is for firefox and can stop that process, as shown below.
# Find a process named Firefox and pass it to the Stop-Process command, which ends it
Get-Process firefox | Stop-Process
The pipeline allows you to string together as many commands as you’d like as long as the commands accept pipeline input.
Remote Communication
PowerShell isn’t just relegated to the computer on which it’s installed on. It can just as easily run commands on remote computers. To do that, it uses PowerShell Remoting (PSRemoting). PSRemoting is a feature that connects to remote computers and executes commands just like the computer was local.
For example, perhaps you’d like to stop the Windows Update service on your local computer. You could do that with Stop-Service -Name wuauserv
.
To run that same command on a remote computer, “wrap” that command in a script block and pass that scriptblock to the Invoke-Command
command.
Invoke-Command -ComputerName SRV -Scriptblock { Stop-Service -Name wuauserv }
PowerShell also has other related remote communication commands like Test-Connection
and Test-NetConnection
to ping, discover port status, and run traceroutes on remote computers.
Test-NetConnection -ComputerName www.google.com -Port 80
Conclusion
PowerShell is a phenomenal tool to help IT pros, sysadmins, developers, or anyone else managing computer systems. It’s a tool that should be in everyone’s toolbelt through its foundational commands coupled with community modules and the ability to create your own scripts.
To learn more, check out all of the others’ posts on PowerShell here and get started automating!