💾 Archived View for pwshnotes.flounder.online › gemlog › 2021-10-24-objects.gmi captured on 2021-12-04 at 18:04:22. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2021-12-03)

-=-=-=-=-=-=-

Objects

Objects are important in PowerShell because PowerShell is based on objects and because an object-oriented shell differs significantly from text-based shells.

Conceptually, objects represent real-life objects. Take an apple for example. An apple is an object. It might have a property called color. The value of color might be green. The apple might have a method called pick. If you call pick on the apple then it might move from a collection of apple objects called tree to a collection called basket. An object that we can use is called an instance. It is a live example from a blueprint for objects which is called a class.

Commands that you type into PowerShell are still text. But all outputs are objects and many cmdlets accept objects as input.

Take the exercise of listing files in the current directory as an example. Let's say we're on Linux and want to list the contents of /usr/bin. If you're on Windows, you can try C:\windows\system32 instead. Below, I have two commands which you can try in your shell: Set-Location and Get-ChildItem. Then, at the bottom of the code block, I have example output which should be similar to your output.

Set-Location /usr/bin
Get-ChildItem

    Directory: /usr/bin

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-r--            9/4/2021 12:26 PM                core_perl
d-r--           9/17/2021  7:10 AM                lou_maketable.d
d-r--           7/18/2021 12:20 PM                site_perl
d-r--          10/16/2021 11:57 PM                vendor_perl
--r--           9/29/2021  8:56 AM          59552 [
l----           8/31/2021  8:28 AM              8 2to3 -> /usr/bin/2to3-3.9
--r--           8/31/2021  8:28 AM             95 2to3-3.9
--r--           8/10/2021  4:11 AM          14168 411toppm
--r--          10/15/2020 12:56 AM          14176 4channels
--r--            9/7/2021 10:11 PM             36 7z
...

We see a listing of files and directories printed to the shell as text. But what is really being output by Get-ChildItem is a collection of FileInfo and DirectoryInfo objects.

We can demonstrate that Get-ChildItem is outputting objects by asking PowerShell what objects it is seeing. Here, I'm using the pipe symbol which is Shift + \ on my keyboard. You can also copy and paste the code from this page into your shell. Below is example output.

Get-ChildItem | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.IO.DirectoryInfo
System.IO.FileInfo

Note this also demonstrates object input. Get-Member receives its input from Get-ChildItem. And Select-Object receives its input from Get-Member.

So PowerShell reports that it is seeing a collection of FileInfo and DirectoryInfo objects. This differs from text-based shells which would only output text.

We can demonstrate text-based output by calling a native command from PowerShell. On Linux, we can use ls which outputs information about files and directories much like Get-ChildItem.

ls | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.String

Here we see the output received by PowerShell is still an object. But the fact the object is of type String tells us that the underlying output is text-based and not the more complex output typical from PowerShell cmdlets. So even though ls and Get-ChildItem perform the same function, they have different types of output.

Note that ls on Windows is an alias for Get-ChildItem. So its output will also produce FileInfo and DirectoryInfo objects. On Windows, many of the familiar commands are built into cmd.exe (internal commands) and are not directly available to PowerShell. If you want to demonstrate text-based output on Windows, try using ipconfig.

It is important to remember that useful objects are only output by PowerShell cmdlets. And text output from older commands remains text. Running older commands in PowerShell does not magically produce meaningful objects. This often confuses new users who try to use PowerShell utilities like Select-Object or Get-Member and don't understand why those fail to work properly when receiving input from text-based commands. Cmdlets require rich objects to fully function.

Since objects carry properties and methods with them, it is easy to discover what can be done with a given object. For example, we can use Get-Member to display the properties and methods for file objects.

Get-ChildItem -File | Get-Member 

   TypeName: System.IO.FileInfo

Name                      MemberType     Definition
----                      ----------     ----------
AppendText                Method         System.IO.StreamWriter AppendText()
CopyTo                    Method         System.IO.FileInfo CopyTo(string dest…
Create                    Method         System.IO.FileStream Create()
...
Attributes                Property       System.IO.FileAttributes Attributes {…
CreationTime              Property       datetime CreationTime {get;set;}
CreationTimeUtc           Property       datetime CreationTimeUtc {get;set;}
...
FullName                  Property       string FullName {get;}
Target                    CodeProperty   System.String Target{get=GetTarget;}

We can use this information to change the output to the shell. For example, recall that, in the first example, Get-ChildItem output the Mode, LastWriteTime, Length, and (file) Name. But, now that we know how to list all the file properties, we can choose different properties for our output. Here, I ask for FullName and Target.

Get-ChildItem -File -Path "arp*" | Select-Object -Property FullName,Target | Format-Table -AutoSize

FullName                       Target
--------                       ------
/usr/bin/arpd                  
/usr/bin/arping                
/usr/bin/arptables-nft         /usr/bin/xtables-nft-multi
/usr/bin/arptables-nft-restore /usr/bin/xtables-nft-multi
/usr/bin/arptables-nft-save    /usr/bin/xtables-nft-multi

While this might seem complicated now, what we're demonstrating is that there is a way to list what columns of information are available and to select only the columns that interest us. We can do that without having to master an additional domain-specific language like awk. And a command like "Get-ChildItem | Select-Object -Property FullName" always outputs the FullName property without us having to write different code if the inputs change.

Another important aspect of objects is type.

Think about this command:

1+1

The correct answer is 2.

Another correct answer is 11.

That's because it is not clear whether we are talking about adding two numbers (which produces 2) or concatenating two letters (which produces 11).

Objects clear up this ambiguity by associating a type with each object.

If we want to disambiguate our example, we can ask PowerShell what objects it is seeing:

1 | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.Int32


'1' | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.String


[char] '1' | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.Char


'1'[0] | Get-Member | Select-Object -Property TypeName -Unique

TypeName
--------
System.Char

Above we see that a number shows as type Int. A string (with one character) shows as type String. And PowerShell's equivalent of character literals are shown as type Char. So, anytime the data you're looking at is ambiguous, you can use Get-Member to learn more about it. Then you can predict how the objects will behave. Or you can understand why some code might not be working.

PowerShell cmdlets input and output objects. Objects provide us with much more information than what is practical with text alone. We can discover the type, properties, and methods available from unfamiliar objects. And we can focus our attention on a few properties without having to parse any text.

Created: Sunday, October 24, 2021

Updated: Sunday, October 24, 2021