In my previous post in this series, I discussed how to set up your PowerShell profile so that you could start collecting shortcuts and tools into it that will make working with PowerShell interactively much, much easier. In this post, I’d like to take a step back and talk about what distinguishes PowerShell from other shells and what that means for how we use it. This leads to a good question:
What makes PowerShell different from other shells?
To answer this question, we have to first take a look at how most command shells have traditionally done their work.
Text Pipelines
Traditionally, shells have relied on text — text for input and text for output. If you had command in the Command Prompt that you need to filter for specific information, you would send the output of that command to another one whose job it was to look only for a particular sequence of characters.
:: Findstr outputs lines matching either SERVICE NAME or RUNNING
:: in the output of the SC command
sc query | findstr "SERVICE_NAME RUNNING"
:: ^ Pipe character tells shell to pass 'sc' output to 'findstr'
The basic unit of operation for most shells is text characters. The shell passes a stream of text from one command to another. Each command in the pipeline operates in turn on sets of the characters it gets from the previous command — perhaps delimiting them by word boundaries with spaces or tabs, or treating each line as a distinct item to work with by using line breaks. It manipulates those characters, or groups of them, and passes it changes on down the pipeline to the next command. This is a bit of an oversimplification, but it should suffice to say that text is lingua franca of most command shells.
Object Pipelines
What makes PowerShell unique is that its basic unit of operation is objects. We could quibble over the details of that statement, but from the perspective of a PowerShell user, they are working with objects, not text.
Take, for example, the PowerShell implementation of the sc
command line I showed you above:
gsv | ?{ $_.Status -eq 'Running' }
This cryptic command line does pretty much the same thing as the previous example with sc
, but it is actually working with objects.
“But wait,” you say, “Isn’t it just filtering through text output like findstr
does?
Actually, no, it’s not, and that is what makes PowerShell so powerful, and so easy to work with…
The gsv
command is an alias for Get-Service
and ?
is an alias for Where-Object
. If we were to expand that last command out and reconstruct it a bit, it would look like this:
Get-Service | Where-Object -Property Status -EQ -Value Running
Get-Service
is actually passing objects to the Where-Object
cmdlet, which looks at the properties of those objects and only returns (passes on down the pipeline) those whose value is equal to “Running”.
This notion of “Properties” lets us do things like this:
Get-Service | Sort-Object -Property Status
This kind of filtering and sorting in text based shells is much more cumbersome. If, for example, the commands themselves do not natively support it, sort on a “column” of text can require a lot of extra work. PowerShell lets us do this with ease, because it’s using objects.
What is an Object anyway?
If you’ve used PowerShell for any time at all, you’ve likely stumbled over a reference to objects — and if you haven’t yet, you will. But what exactly is an “object” and why does it matter?
It’s a bit academic, but once we understand what an “object” is, and how PowerShell stitches them together in a “pipeline”, we will far more efficient using PowerShell, interactively and when we create scripts.
An object is a container for data and code.
That’s my personal definition. It’s short and to the point, and it drives to the two key aspects of what most PowerShell output objects have in them. You can compare objects to cars, for example:
Container | Object | Car |
---|---|---|
Data | Property | Option |
Code | Method | Feature |
An object’s data is accessed through its properties, which are like the options on a car — for example, its color being red. An object’s code is accessed through its methods, which are like the features of a car — for example, the ability to accelerate, stop, or engage all-wheel drive.
So, here’s an example of what that might look like for either:
Object | Windows Service | Car | Mustang |
---|---|---|---|
Property | ServiceName | Option | Leather Interior |
Method | Start | Feature | Set Cruise Control |
Now, obviously a car has thousands of options and features, and objects have only a few, but another way that you can think of the distinctions between properties and methods is that properties are something, and methods do something. Or, if you like language, properties are nouns, methods are verbs:
Object | Car | Thing | Word |
---|---|---|---|
Property | Option | Is | Noun |
Method | Feature | Does | Verb |
We can explore what various objects are and do inside PowerShell with the Get-Member
cmdlet:
Get-Service | Get-Member
Sample output:
TypeName: System.ServiceProcess.ServiceController
Name MemberType Definition
---- ---------- ----------
Name AliasProperty Name = ServiceName
RequiredServices AliasProperty RequiredServices = ServicesDependedOn
Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs)
Close Method void Close()
Continue Method void Continue()
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Dispose Method void Dispose(), void IDisposable.Dispose()
Equals Method bool Equals(System.Object obj)
ExecuteCommand Method void ExecuteCommand(int command)
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Pause Method void Pause()
Refresh Method void Refresh()
Start Method void Start(), void Start(string[] args)
Stop Method void Stop()
WaitForStatus Method void WaitForStatus(System.ServiceProcess.ServiceControllerStatus desiredStatus), ...
CanPauseAndContinue Property bool CanPauseAndContinue {get;}
CanShutdown Property bool CanShutdown {get;}
CanStop Property bool CanStop {get;}
Container Property System.ComponentModel.IContainer Container {get;}
DependentServices Property System.ServiceProcess.ServiceController[] DependentServices {get;}
DisplayName Property string DisplayName {get;set;}
MachineName Property string MachineName {get;set;}
ServiceHandle Property System.Runtime.InteropServices.SafeHandle ServiceHandle {get;}
ServiceName Property string ServiceName {get;set;}
ServicesDependedOn Property System.ServiceProcess.ServiceController[] ServicesDependedOn {get;}
ServiceType Property System.ServiceProcess.ServiceType ServiceType {get;}
Site Property System.ComponentModel.ISite Site {get;set;}
StartType Property System.ServiceProcess.ServiceStartMode StartType {get;}
Status Property System.ServiceProcess.ServiceControllerStatus Status {get;}
ToString ScriptMethod System.Object ToString();
My hope is that we took some of the mystery, or even anxiety, out of objects for you, and make working with them, and PowerShell, a lot clearer and more straightforward. In my next post in this series, I’ll talk more about objects and how we can make use of their properties and methods.
Additional Reading
- Documentation: about_Objects
- Documentation: Understanding Important Windows PowerShell Concepts