Fun With PowerShell Objects – Creating Objects from C#

Introduction

This is the next installment in my series on creating objects in PowerShell. In the first installment we showed how to create an object using the class type introduced in PowerShell 5. That covered the basics, and in the last installment of this series we’ll cover some advanced techniques.

In the last two installment of this series, I covered the various ways to create objects using the PSCustomObject. We saw how to create it using the New-Object cmdlet, then how to add your custom properties to it using the Add-Member cmdlet. In the subsequent post we saw how to add new methods to it.

In this post, we’ll cover something new, creating an object based on C# code!

For all of the examples we’ll display the code, then (when applicable) under it the result of our code. In this article I’ll be using PowerShell Core, 7.2.1, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

Additionally, be on the lookout for the backtick ` , PowerShell’s line continuation character, at the end of many lines in the code samples. The blog formatting has a limited width, so using the line continuation character makes the examples much easier to read. My post Fun With PowerShell Pipelined Functions dedicates a section to the line continuation character if you want to learn more.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Why C#

You may be asking yourself, why integrate C# code into PowerShell? Why not just define our objects using PowerShell? There are several reasons, especially if you are working with a team of C# developers, or are a C# developer yourself.

First, it can make testing your C# classes easy. You can code the class and save it in a .CS file. Then run some simple PowerShell to create a new object from your class and test its various properties and methods. This lets you make changes easily and test again. All without having to create a full blown C# project just to test.

It also allows for code reuse. Let’s say your C# developers have created a library to do some calculations, and you need to use one of the methods from that library, but that library expects you to pass in an object based on a class.

Let’s further the example, perhaps you have the task of reading in a CSV file, doing a calculation for each row, then outputting another CSV file, or maybe even a JSON file. This is a one time use, so you don’t want to go to the effort of creating a full blown C# project.

Using the techniques in this demo, you could simply access the C# file in which the class was defined, and generate an object from it in PowerShell. Then all you’d have to do is populate the object and pass it into the library to do the calculation, and output the result.

These are just a few simple examples, I’m sure you’ll come up with many more as the need arises. I’ll be honest, this isn’t something you will need to do a great deal, but when you do you’ll appreciate knowing how.

Embedding a C# Class in your PowerShell

In this first method, we’ll define a standard C# class within a here string then add it as a new data type in PowerShell. Once it exists as a type, we can then generate new objects from it. Let’s take a look at a very simple class definition.

$code = @"
using System;

public class SchemaTable
{
  public string DatabaseName;

  public string SchemaTableName(string pSchema, string pTable)
  {
    string retVal = "";  // Setup a return variable

    retVal = pSchema + "." + pTable;

    return retVal;

  } // public SchemaTableName

  public string FullName(string pSchema, string pTable)
  {
    string retVal = "";  // Setup a return variable

    retVal = this.DatabaseName + "." + pSchema + "." + pTable;

    return retVal;

  } // public FullName

} // class SchemaTable

"@

If you’ve read this far I’m going to assume you are familiar with C#, at least the basics of it, so I’ll keep this explanation at a high level.

We start by declaring a class named SchemaTable. The next line declares a variable (which will become a property) called DatabaseName.

I then create the first of two functions (which will become our methods). The SchemaTableName simply takes the two passed in values of pSchema and pTable and concatenates them together with a period between them.

The second, FullName, takes the value in DatabaseName and concatenates them with the schema and table name parameters, again using a period as a separator in the return string.

Next, we need to add this class as a new data type in PowerShell. You are already familiar with many data types, such as int, string, and more. We simply want to add a new data type to our PowerShell environment.

To do so, we will use the Add-Type cmdlet.

Add-Type -TypeDefinition $code `
         -Language CSharp

The first parameter, TypeDefinition, takes the C# code we defined in the here string. The second, Language, is pretty obvious. We simply need to let PowerShell know what language this code was written in.

As of right now, the only supported language is C#. Because of this, if you leave off the -Language CSharp parameter, it will default to C# as the language. I included it here for completeness, but will omit it for future examples in this post.

So now we’ve defined a class in C#, and have added it as a new data type in PowerShell. How then do we create an object from it?

We’ll turn to our old friend, New-Object.

$result = New-Object -TypeName SchemaTable

That’s it, that simple one line will create our new object based on the C# code we defined in the $code variable. You can even use Get-Member to display its properties and methods like you would with any other object.

$result | Get-Member

Result:

Name            MemberType Definition
----            ---------- ----------
Equals          Method     bool Equals(System.Object obj)
FullName        Method     string FullName(string pSchema, string pTable)
GetHashCode     Method     int GetHashCode()
GetType         Method     type GetType()
SchemaTableName Method     string SchemaTableName(string pSchema, string pTable)
ToString        Method     string ToString()
DatabaseName    Property   string DatabaseName {get;set;}

It contains the standard methods and properties built into all objects, but it also has the three we defined: FullName, SchemaTableName, and DatabaseName.

We can use these properties and methods just like ones in any other object. Let’s set the DatabaseName property, then display it.

$result.DatabaseName = 'MyDB'
$result.DatabaseName

Result:

MyDB

Likewise, we can access the methods we created. Here’s the SchemaTableName method.

$result.SchemaTableName('ASchema', 'ATable')

Result:

ASchema.ATable

And for completeness, the FullName method.

$result.FullName('ASchema', 'ATable')

Result:

MyDB.ASchema.ATable

C# Classes with Static Methods

In the original post in this series on basic PowerShell classes, I mentioned the concept of static methods and properties. As static method or property is simply one that can be called without having to generate a new object.

While we’ll circle back around to discuss implementing static methods and properties in PowerShell classes in the final post in this series, it is likely you’ll encounter C# classes with static methods and properties. As such we’ll go ahead and cover them here, while we are talking C#.

In the code below, I’ve defined a class with one method, and labeled it as static. In reality you will encounter many classes that have a mix of static and non-static members, but for this post we’ll keep the example simple.

$code = @"
using System;

public class StaticSchemaTable
{
  public static string FullName(string pSchema, string pTable)
  {
    string retVal = "";

    retVal = pSchema + "." + pTable;

    return retVal;

  } // public static FullName
} // class StaticSchemaTable
"@

As you can see, I’ve simply used the static keyword as part of the FullName function declaration. I also changed the name of the class, otherwise the code is the same as the previous demo.

Now we need to add this as a new type in our current PowerShell session.

Add-Type -TypeDefinition $code

Calling our static method requires different syntax. First, it won’t be necessary to create an object from it. Second, we’ll need to use the full name of our class in brackets, followed by two colons. We then indicate the name of the static function to call, and pass in any parameters.

$result = [StaticSchemaTable]::FullName('MySchema', 'myTable')
$result

Result:

MySchema.myTable

Static methods and parameters aren’t something that’s used a great deal, but they are used so you should know how to handle them.

Creating an Object from A C# File

While it is certainly possible to embed C# code right in your PowerShell, this could lead to some issues. The moment a developer makes a change to their .cs file, you are now out of sync. You don’t want to have to keep cutting and pasting all the time.

It makes far more sense, then, to simply access the C# file with the class definition, and load it at run time.

First, you need to create a C# file with the sample code. Here is what I put in my .cs file:

using System;

public class StaticSchemaTableInFile
{
  public static string FullName(string pSchema, string pTable)
  {
    string retVal = "";

    retVal = pSchema + "." + pTable;

    return retVal;

  } // public static FullName
} // class StaticSchemaTableInFile

This is the same static class you just saw, with the minor change to the class name.

In the next sample, I simply build the path to the file name, then use the Get-Content to read it.

$csPath = 'C:\Users\arcan\OneDrive\BlogPosts\Markdown\'
$file = "$($csPath)Fun-With-PowerShell-Objects-Part 3.cs"
$code = Get-Content $file | Out-String

Get-Content will read the contents of the file. By default Get-Content reads it as an array with each line in the file being an element, so we’ll have to pipe it through the Out-String cmdlet to convert it to a single string. This string is then stored in the $code variable. Of course you’ll need to update the path and file variables you used on your computer.

Now we do just like the previous demo, call Add-Type then run it.

Add-Type -TypeDefinition $code
$result = [StaticSchemaTableInFile]::FullName('mySchema', 'myTable')
$result

Result:

mySchema.myTable

Again, I reused the example from the static demo but we could also have used the first example, or any standard C# file containing class definitions.

Other Ways To Add Types

While outside the scope of this post, I did want to mention there are two other ways you can add new data types to your PowerShell scripts. First, Add-Type will let you load types stored in an assmebly, in other words a .dll file.

Second, if you are running on a Windows computer you can add types stored in native Windows APIs. If you want to learn more about these, I’ll refer you to the Add-Type Documentation at Microsoft.

Persistance

One last thing you need to be aware of. When you add a type it does not persist between sessions. The moment you close your command window or VSCode, that type goes away. You’ll need to recreate it the next time you run your script.

This is probably a good thing, as it’s doubtful you will need to use these types on a daily basis. Should you need to, though, you’ll have to edit your PowerShell profile and have them added within it.

Conclusion

In this post we saw how to create custom objects from C# classes. They could be embedded in our PowerShell code, or stored in external files. The subject of static methods and properties were mentioned, along with a demo on how to use them.

In the next post we’ll see a very useful technique, and cover the ability to add our own custom methods and properties to existing objects that others created, including ones built right into PowerShell.

The demos in this series of blog posts were inspired by my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Fun With PowerShell Objects – Adding Methods to PSCustomObject

Introduction

In the previous installment of this series, I covered the various ways to create objects using the PSCustomObject. We saw how to create it using the New-Object cmdlet, then how to add your custom properties to it using the Add-Member cmdlet.

In this post we’ll learn how to add our own methods to our objects using script blocks. Before we go on, just a quick reminder on vocabulary.

In object oriented terminology, objects have properties and methods. From the perspective of the script writer who uses our object, they only know of the properties and methods we expose. They don’t know, or care, how we implemented them.

From the perspective of us, the authors of the code to create the object, it’s a little different. What the end user calls properties we store in variables. We implement our objects methods using functions.

When we are talking about our code in terms of writing our object, you will frequently see the terms properties and variables used interchangeably. Likewise you’ll see the terms method and function used interchangeably.

For all of the examples we’ll display the code, then (when applicable) under it the result of our code. In this article I’ll be using PowerShell Core, 7.2.1, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

Additionally, be on the lookout for the backtick ` , PowerShell’s line continuation character, at the end of many lines in the code samples. The blog formatting has a limited width, so using the line continuation character makes the examples much easier to read. My post Fun With PowerShell Pipelined Functions dedicates a section to the line continuation character if you want to learn more.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Script Blocks

Before we get started, it’s important to understand the concept of a script block. A script block is a piece of code encapsulated within squiggly braces {}. This code is meant to execute as a unit. Here’s an example you’ve probably seen before.

$x = 1
if ($x -eq 1)
{ Write-Host 'Yep its one' }

The code on the last line is the script block. This unit of code, within the squiggly braces, will execute should the if statement evaluates to true.

It’s possible to define your own script blocks, and store them in a variable.

$hw = {
        Clear-Host
        "Hello World"
      }

Here I’ve generated a simple block with two lines. The first clears the display, the second prints Hello World.

Now you have a variable, $hw, holding a script block. How can we use this?

First, we could execute the script block stored in the variable. To do so, we need to precede the name of the variable with an ampersand &. The ampersand is the PowerShell shortcut for execute the code block contained in this variable.

& $hw

Result:

Hello World

Although it’s difficult to show, the display did indeed clear before displaying our text.

Note the space between the & and the variable name is optional, this works too.

&$hw

Personally I think the space makes it a bit easier to read, not to mention it’s easier for the eye to notice the &. Whichever way you go, I suggest picking a format and sticking to it.

There are some interesting ways we can use this concept. Of course we’ll look at using script blocks to add new methods to an object in a moment, but another fun thing you can do is pass a script block into a function.

A quick note, it is generally considered poor practice to have Write-Host statements within a function. Since this is just a simple demo though, we’ll use them just to illustrate our concepts.

function Run-AScriptBlock($block)
{
  Write-Host 'About to run a script block'

  & $block

  Write-Host "Block was run"
}

Run-AScriptBlock $hw

Result:

Hello World
Block was run

The first line to display "About to run…." did execute, but it was wiped out due to the Clear-Host in the script block.

The script block then displayed Hello World, and returned control to the function. The function then displayed "Block was run" then exited.

The PowerShell testing tool, Pester, makes extensive use of this functionality to pass the code blocks being tested into Pester’s unit testing functions.

Your imagination is probably running wild at the various ways you can use this. For example, you could build a string of PowerShell code based on certain conditions, then once the string of code is complete execute it.

At this point you have a nice foundation on the concept of script blocks, so let’s move on to the main topic of this post.

Starting Point

This post picks up where the previous one left off. If you recall, our previous post built a function to generate a custom object of type PSCustomObject. If you need an explanation please go back and read part 1 of this series, but to make it easy for you I’ll reproduce the function needed to create the object we’ll be working with.

function Create-Object ($Schema, $Table, $Comment)
{
  # Build a hash table with the properties
  $properties = [ordered]@{ Schema = $Schema
                            Table = $Table
                            Comment = $Comment
                          }

  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject -Property $properties

  Add-Member -InputObject $object `
             -MemberType AliasProperty `
             -Name 'Description' `
             -Value 'Comment'

  # Return the newly created object
  return $object
}

$myObject = Create-Object -Schema 'MySchema' `
                          -Table 'MyTable' `
                          -Comment 'MyComment'
$myObject

Adding a Method (aka Function) to an Object

With the knowledge above, combined with what we learned in the previous post, it turns out adding a simple function to an object is easy. First, we need to define our function in a script block. This function will combine the schema name and the table name with a period to separate the two.

$block = {
           $st = "$($this.Schema).$($this.Table)"
           return $st
         }

In this example I used string interpolation to build my return string. (For more on string interpolation, see my post Fun With PowerShell Strings.)

Note my use of the $this keyword. Just like with objects generated by the more modern classes in PowerShell 5 and beyond, $this is used to represent the current instance of our custom object. Thus we’ll be getting the schema and table names for the current object, stored in $myObject, and not one in another variable that was instantiated using the same code.

If you aren’t a fan of string interpolation, you could have opted for concatenation with $st = $this.Schema + '.' + $this.Table to generate the return value, but interpolation is the generally accepted best practice for building strings.

Concatenation is generally slower and takes more processing power than interpolation. Granted in this case it is barely measurable, but done over a dataset of millions of rows you might see an impact.

With the schema-table string ($st) built it is then returned.

Now we will use the Add-Member cmdlet to add this function to our custom object. Assuming you have already run the function to create the $myObject variable, shown in the Starting Point section, you can use the following code to achieve our goal.

Add-Member -InputObject $myObject `
           -MemberType ScriptMethod `
           -Name 'SchemaTable' `
           -Value $block

I start by passing in the object I wish to add a member to, our $myObject variable.

Next I indicate what type of member we are adding. ScriptMethod is the value to pass in to MemberType to indicate the data in the variable is a script block and should be manifested as a method.

The Name is next, in other words what we want to name this method. Finally into the Value parameter we pass in the variable holding the script block.

Once you add this new member, you can simply call it using the dot notation, with one important caveat. Because this is a method, you need to add parenthesis to the name of the method.

$myObject.SchemaTable()

Result:

MySchema.MyTable

Using the parenthesis lets PowerShell make the distinction between a property and a method.

Parameters

What’s that? You in the back row raising your hand, what did you say? Parameters? You want to add parameters to your new method?

Well, OK because you asked so nice.

This turns out to be pretty easy. We just need to add a param section within our script block.

$block = {
           param ($DatabaseName)
           $dst = "$DatabaseName.$($this.Schema).$($this.Table)"
           return $dst
         }

On the first line of our script block we use the param keyword, then have a list of our parameters within parenthesis. Here we only have one, $DatabaseName, but we could have more separated by commas.

I then build a string that uses the passed in database name, with the schema and table names already in the object, and finally return it.

Next, I use Add-Member to add this function to our object just like I did with the previous example, the only difference being the name and the variable with our script block. Now we can call it.

$myObject.DatabaseSchemaTable('MyDBName')

Result:

MyDBName.MySchema.MyTable

Conclusion

This post began with an explanation of script blocks. Using this knowledge we added new methods to our existing object. One even allowed us to pass in a parameter.

In in the next post we’ll see how to create custom objects from bits of C# code. Later on we’ll see how to add our own properties and methods to an existing object created by PowerShell.

Well conclude this series by returning to our discussion of PowerShell classes by looking at some advanced features of the built in class construct.

The demos in this series of blog posts were inspired by my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

A New Year, A New Blog Layout

After a few years I decided it was time to update the blog with a new layout. I liked the look of the previous one, but the three-column layout had some limitations.

The center column, where the main content resided, did not give much space for code samples. It was wrapping many lines of code unnecessarily and made it harder to read.

This new format is trimmed down, cleaner, and feels less cluttered. It also provides more space for the code samples, which is the important part.

Happy New Year and hope you enjoy the new format. Feel free to leave any feedback in the comments below.

Fun With PowerShell Objects – PSCustomObject

PSCustomObject Sample

Introduction

Before the holidays I had started a series on classes and objects in PowerShell. If you haven’t read my post Fun With PowerShell Classes – The Basics you should give it a quick read. There are terms that were defined in it that we’ll be using here.

For this post I’ll begin a series on the use of PSCustomObject. Prior to the addition of classes in PowerShell 5.0, this was the technique needed to create your own customized objects. It still has a lot of validity today though, as you can use these techniques to extend the objects other people defined, including those already built into PowerShell.

In addition, understanding the use of PSCustomObject will give you a better understanding of the way classes work.

First let me mention that for all of the examples we’ll display the code, then under it the result of our code when applicable. In this article I’ll be using PowerShell Core, 7.2.1, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

Second, be on the lookout for the backtick ` , PowerShell’s line continuation character, at the end of many lines in the code samples. The blog formatting has a limited width, so using the line continuation character makes the examples much easier to read. My post Fun With PowerShell Pipelined Functions dedicates a section to the line continuation character if you want to learn more.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Code to Generate Our PSCustomObject

For these demos, I’m going to wrap the creation of our objects within a function. This is a common technique which allows us to create multiple objects based on a single set of code. Note this isn’t required, you could use these techniques anywhere in your code. I just find placing it in functions makes for greater reuse.

If you need a refresher on PowerShell functions, I’ll refer you back to my posts on functions: Fun With PowerShell Basic Functions; Fun With PowerShell Advanced Functions; and Fun With PowerShell Pipelined Functions.

Let’s take a look at our first example, then break down each line.

function Create-Object ($Schema, $Table, $Comment)
{
  # Build a hash table with the properties
  $properties = [ordered]@{ Schema = $Schema
                            Table = $Table
                            Comment = $Comment
                          }

  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject `
                       -Property $properties

  # Return the newly created object
  return $object
}

Our first line, obviously, defines our basic function. For this example I will be creating an object that holds the schema and table names for a database. It also will allow for a comment, so these are the three parameters that are passed in.

To add a list of properties to our object, we need to use a hash table. I define the hash table with three properties, Schema, Table, and Comment, and assign the parameter variables we passed in for their respective values. And yes, I do have a post on hash tables if you wish to know more about them, Fun With PowerShell Hash Tables.

Next is where the magic occurs. I call the cmdlet New-Object. For its TypeName parameter I use the value of PSObject. This will create a variable of type PSCustomObject. I then pass in my hash table name for the Property parameter.

This is assigned to the variable $object. In the final line I return that value to the calling code.

Before someone points it out, yes I could have made the last line of the function simply New-Object –TypeName PSObject -Property $properties and not assigned it to a variable. As I explain in my previously mentioned posts on functions, not consuming the output within the function returns the value to the code that called it.

Assigning to a value within my function, then returning that value, gives me some additional flexibility. Primarily I could use the Write-Verbose and Write-Debug statements to echo additional debugging information back to the developer (or user). It also allows for easier integration with testing tools, such as Pester.

For more info on Write-Verbose and Write-Debug, see my posts Fun With PowerShell Write-Verbose and Fun With PowerShell Write-Debug.

Creating Our Custom Object

Now that we have the function created, we can call it to create our custom object. We’ll then display its properties.

$myObject = Create-Object -Schema 'MySchema' `
                          -Table 'MyTable' `
                          -Comment 'MyComment'

# Display all properties
$myObject

Result:

Schema   Table   Comment
------   -----   -------
MySchema MyTable MyComment

As you can see, simply running the name of our variable produces a table. Across the top are the names of our properties, below it are the values we passed into the function to use as values.

If we want to prove to ourselves this is indeed a PSCustomObject, we can use the GetType method.

$myObject.GetType()

Result:

IsPublic IsSerial Name            BaseType
-------- -------- ----            --------
True     False    PSCustomObject  System.Object

As you can see in the Name column, it is indeed of type PSCustomObject!

Like any object, we can assign new values by referencing the individual properties.

$myObject.Schema = 'New Schema'
$myObject.Comment = 'New Comment'
$myObject

Result:

Schema     Table   Comment
------     -----   -------
New Schema MyTable New Comment

In the output, you can see the values for Schema and Comment were updated. The original value for the Table property remained unchanged.

Adding Properties One At A Time

There is an alternate method we can use to create a custom object. We can create an empty object, then use the Add-Member cmdlet to add each property individually.

Let’s rewrite our function to use this methodology.

function Create-Object ($Schema, $Table, $Comment)
{
  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject

  # Add-Member by passing in input object
  Add-Member -InputObject $object `
             –MemberType NoteProperty `
             –Name Schema `
             –Value $Schema

  # Alternate syntax, pipe the object as an input to Add-Member
  $object | Add-Member –MemberType NoteProperty `
                       –Name Table `
                       –Value $Table

  $object | Add-Member -MemberType NoteProperty `
                       -Name Comment `
                       -Value $Comment

  return $object
}

The function declaration is the same as in our first example. We then create an empty object through the line $object = New-Object –TypeName PSObject. This object now exists, but has none of our custom properties. Yet!

Now we are going to call the Add-Member cmdlet. Add-Member allows us to add new properties and methods to an existing object.

The first parameter, InputObject, is used to indicate what object we want to work with.

The next parameter is MemberType. There are a variety of types we can add to a custom object. In this case we want to add a text property, so the correct value to use is NoteProperty. We’ll see examples of other member types as we progress through this series.

The next two parameters are pretty self explanatory. The Name is what we want to call this property, and Value is the value we want it to have.

We then move on to add the Table property. In this example I wanted to show the alternative format for using Add-Member. You can take the object you want to add a member to, and pipe it into the Add-Member cmdlet. I’ve done this here for the Table property, as well as for the final property Comment.

Using this function has identical results as the previous example.

$myObject = Create-Object -Schema 'MySchema' `
                          -Table 'MyTable' `
                          -Comment 'MyComment'
$myObject

Result:

Schema   Table   Comment
------   -----   -------
MySchema MyTable MyComment

So why use Add-Member? Clearly the first example where we used a hash table to declare our property list was more compact.

Think about what we did here. We added new properties to an existing object! In this case it was a custom object we created. but this could be any PowerShell object. For example, we could have a list of file system objects returned to us by the Get-ChildItem cmdlet. Using Add-Member we have the ability to add new properties (and methods) to those objects.

We’ll see an example of this very thing in a future blog post, but for now let’s move on to the final section in today’s post.

Creating Property Aliases

If you’ve been in IT for any length of time, you’ve probably encountered the situation where two different groups refer to the same property by two different names. In our example, let’s say the DBA’s refer to the comment property as Comment. They would like to use that property name when they use your script.

Your software developers though don’t think of this as the comment property, instead they call it Description. They complain that having to use the property name "Comment" is causing a lot of coding errors.

This is one of those rare times we can make everyone happy, and we do so through the use of a property alias.

We’ll start with the same $object variable we left off with in the previous example. We’ll then use Add-Member to add a new alias.

Add-Member -InputObject $myObject `
           -MemberType AliasProperty `
           -Name 'Description' `
           -Value 'Comment' `
           -PassThru

Result:

Schema     Table   Comment     Description
------     -----   -------     -----------
New Schema MyTable New Comment New Comment

The first thing to note is the MemberType. Instead of a NoteProperty, we are using the type AliasProperty. This will let the Add-Member cmdlet know we are simply adding an alternate name for an existing property.

The Name parameter is the name for the alias. The Value is the name of the already existing property.

You’ll also note I added a switch to Add-Member, PassThru. In our previous examples, leaving this off ran the code but displayed no output. If want to see the results though, you can add the PassThru switch and the new values will be displayed in the terminal, as you saw in the Result section above.

Our alias added, you can see a new column Description. The value under it is identical to the one for comment.

Let’s change the Description property and see what happens.

$myObject.Description = 'The Description'
$myObject

Result:

Schema   Table   Comment         Description
------   -----   -------         -----------
MySchema MyTable The Description The Description

As you can see, both Comment and Description hold the newly updated value. Your users can now use these property names interchangeably.

We can of course update our original function to add the alias at the time the object is created.

function Create-Object ($Schema, $Table, $Comment)
{
  # Build a hash table with the properties
  $properties = [ordered]@{ Schema = $Schema
                            Table = $Table
                            Comment = $Comment
                          }

  # Start by creating an object of type PSObject
  $object = New-Object –TypeName PSObject `
                       -Property $properties

  Add-Member -InputObject $object `
             -MemberType AliasProperty `
             -Name 'Description' `
             -Value 'Comment'

  # Return the newly created object
  return $object
}

$myObject = Create-Object -Schema 'MySchema' `
                          -Table 'MyTable' `
                          -Comment 'MyComment'
$myObject

Result:

Schema   Table   Comment   Description
------   -----   -------   -----------
MySchema MyTable MyComment MyComment

As you can see, the function generated an object that included our alias. In this example I also combined methods. I used a hash table to define our initial set of properties, then used Add-Member to add the alias. I could have also put the addition of the alias in the second version of the function, where each property was added one at a time.

Conclusion

In this post we learned how to create a basic object using PSCustomObject. We added some properties, and even created an alias for one.

Now you may be asking "what about methods? Object can have methods too!" And you would be correct. In the next post in the series we’ll see how to add custom methods to our object.

In future posts we’ll see how to create custom objects from bits of C# code. Then we’ll see how to add our own properties and methods to an existing object created by PowerShell.

We’ll then return to our discussion of PowerShell classes by looking at some advanced features of the built in PowerShell class type.

The demos in this series of blog posts was inspired by my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Happy New Year – Now Go Make Your Bed

Happy New Year!

As we start this new year, I wanted to share a piece of advice that I’ve followed for the last few years, which has helped my mental state.

Make your bed.

Every day.

I know, it sounds simple, but it makes a surprising difference.

First off, you start the day with a “win”. You look at your neatly made bed and get a feeling that you’ve already accomplished something for the day. It puts you in the attitude that you are ready to tackle the next thing.

Now flip it. You are coming to bed after a long day. If you leave your bed unmade, you see a chaotic mess. The sheets are rumpled, it looks like a choppy ocean wave. It does not, to me anyway, look at all inviting.

If your bed was made though, it reminds you of a calm, tranquil lake. Soft, smooth, ready to relax in.

I also make my sheets fun by having a variety of colors. Over time I’d purchase a set with some extra pillowcases from my local big box store. I selected colors I could mix and match. Black, White, Blue, Green, Red, and Brown.

I also picked up some fleece covers to act as my bed spread in colors that complement the sheets. White, Red, Blue, Brown, and Gray. This lets me setup combos like Green and Gray, Black and Red, Black and White, Blue and White (as you can see in the photo at the top), you name it I have lots of fun combos that keep my bedroom looking fresh and different, just with combining sheets and blankets.

Again, I realize this sounds like an extremely simple thing. However, it’s a piece of advice I’ve seen many experts give so I decided to try it, and by golly it does make a difference in my outlook on the day.

Habits are interesting things, once you get them started it annoys you mentally when you skip them. Only rarely have I not made my bed, and that was usually because I was sick and in it. The other few times it was because I overslept and had to run out the door. Those times as soon as I got home I made it because it was mentally annoying me.

You can now build on this habit to improve other areas of your life. Perhaps putting your car keys in a specific spot so you don’t lose them, brushing your teeth, allocating time to update your blog, and more.

Try it, if nothing else you’ll have a nice neat bed.

Fun with Preparedness

Introduction

I have a confession to make. I’m something of what might be called a prepper. Now, does this mean I believe the government is about to clamp down on everyone, or the zombie invasion is upon us?

No, of course not. But I do live in the southern United States, where we regularly have tornadoes, hurricanes, and (sometimes violent) thunderstorms. We also have some wild temperature swings, as I write this tomorrow’s high is predicted to be 72 F, the low should be 39 F.

As such I’ve taken steps to be ready for weather related emergencies. I have a generator to supply power. My kerosene heater can keep me warm on cold nights when the power is out.

In my car I keep a backpack with a few basic supplies should I be away from home and trapped. Blanket, change of clothes, water, food, some camping supplies. Things that will keep me alive and somewhat comfortable should I need to spend the night in or beside my car, or should I need to hike home or to a safe shelter.

In the spirit of gift giving during the holiday season, I wanted to share not one but two (in no particular order) YouTube channels that have taught me a lot about being prepared.

The Sensible Prepper

The first channel I want to share is The Sensible Prepper. He shows various types of gear you can use to be prepared. Beyond that he also shows how everyday items, such as safety pins, plastic bottles, baking soda and more can be used in ways to get you ready for an emergency.

Here is one example, on using plastic bottles for preparedness.

Corporals Corner

The second channel I’ve learned a lot from is Corporals Corner. His channel is focused more on survival in the outdoors. He teaches how to create a wide variety of survival shelters and demonstrates equipment for staying alive when you are in the outdoors.

In some cases, he uses tents, or in other cases he creates entire shelters from nothing but the raw materials he finds in the woods. Corporal Kelly, USMC, has to be the hardest working YouTuber I’ve ever seen. He also knows more about knot tying than any other YouTuber I’ve ever watched.

Here is a recent video where he tests out an emergency shelter available from Amazon and shows the pros and cons.

Conclusion

I hope you’ll enjoy these channels as much as I do and learn some lessons in preparedness as I have. Even just taking a few simple steps can make the difference between being miserable in a weather-related emergency and coming through it comfortably.

Fun with History: The History Guy

Introduction

In the spirit of the holiday season, I wanted to give a little gift back to you, my readers.

I love history, honestly if I weren’t in tech I would likely have become a history teacher of some kind. For relaxing I read a lot of history books and enjoy a lot of history shows on YouTube as well as other platforms.

The History Guy

One of my favorite YouTube channels is The History Guy: History Deserves to Be Remembered. Several times a week he releases roughly 15-minute videos on some event on history. Many are often little-known events, which cross a variety of areas.

Some of course focus on big events, such as the world wars, or the US Civil War. Others might focus on motor sports, microfilm, or major events such as earthquakes or blackouts. Then there are ones that focus on notable, and some not so notable, figures from history.

The history is global in scale, not just US but events from history around the globe.

The Most Important Invention of the 20th Century

Below I’ve embedded my favorite video from his massive library, on the invention of the transistor. This video touches several areas of interest for me. Obviously, the transistor as it applies to computers, but in addition the advances it made possible in communication which appeals to the ham radio operator in me.

Conclusion

Please take a look, I feel sure you’ll enjoy him as much as I do. Then jump over to his YouTube channel and subscribe, then enjoy many more videos from his library.

Happy Holidays!

Fun With PowerShell Classes – The Basics

Introduction

In the last few posts we looked at the use of Enums, a technique closely associated with classes. In this post we’ll start looking at classes themselves. We’ll open with some terminology, then look at our first class.

For the next post in this series I plan to do a history lesson on the use of PSCustomObject. Prior to the addition of classes in PowerShell 5.0, this was the technique needed to create your own customized objects. From there we’ll return to the modern area and get into some advanced class techniques.

First let me mention that for all of the examples we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.2, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Terminology

If you are familiar with object oriented terminology, then this short overview will be familiar to you. However, many who come into PowerShell scripting do not come from a coding background. It’s worth taking a few paragraphs, then, to explain some common terms that will be used in this and future articles.

A class is code that is used as a blueprint to create an object variable in memory. In fact, all variables in PowerShell are objects, even built in ones like strings or integers. Their classes are already defined and ready to be used in the core PowerShell libraries.

The act of creating a new object from a class is called instantiation. You can instantiate multiple variables from the same class.

In most object oriented discussions, the classic example compares a class to a blueprint for a house. From that single blueprint a home builder can create an entire neighborhood of houses.

Each house has properties that can be set to make the houses different from each other, even though they are built from the same blueprint. House color, trim color, number of cars the garage will hold, are all properties that can be set on a per house basis.

Likewise, a PowerShell class has properties. These are made available through variables, and may be things like first name, last name, address, birth date, number of pets, or any number of other items that would apply to this instance of an object built from your class.

A house blueprint may also have tasks assigned to it. "Get building permit from city", for example, or "paint the trim". In the PowerShell world, a class can also have tasks assigned to it. These are created by using functions.

If you aren’t familiar with functions yet, you need to brush up. You can start with my series Fun With PowerShell Functions, then continue through the next few posts which move into advanced functions and pipelined functions.

When it comes to classes, we call these built in functions methods. A method is designed to act on the data within the function itself.

A simple example, you may have three properties, first name, middle name, and last name. You could create a method (in the form of a function) called full name, which concatenates the three parts of the name together, correctly formatting for times when a middle name is absent.

Methods in a class can return a value, but do not have to. We’ll see examples of both in this article.

Also be aware there are special types of properties and methods that are called static properties and static methods. These are pieces of code that PowerShell can execute from the class itself, without creating an object from that class.

We’ll see examples of how to create and use these in our future post on advanced classes, but I wanted to mention them as PowerShell classes have a static function we’ll need to use in order to instantiate new objects.

This short intro just hits the tip of the iceberg when it comes to object oriented methodology, entire books have been written on the subject. Hopefully it provides enough information to get you started.

So now that we’re all on the same page when it comes to terminology, let’s go create a class.

A Very Simple Class

This first example will be very simple. Take a look, then we will go over its parts.

class Twitterer
{
  # Create a property
  [string]$TwitterHandle

}

We begin the definition with the keyword class, followed by what we wish to name our class. In my previous articles on enums we used Twitter data as an example, so let’s stick to that.

After the name of the class we need an opening squiggly brace, and a closing one at the end. In PowerShell squiggly braces are used to define a scrpt block. You’ve seen these before, functions, foreach, if statements and more all use script blocks. Classes are no different, everything in the script block is the class definition.

With classes, as with most script blocks, it’s not necessary to put the opening squiggly brace on the next line, many use class Twitter { on a single line. I just feel having the squiggly braces vertically aligned makes things easier to read.

Within the class I have defined a single property, $TwitterHandle. Before the name of the variable I have indicated the variable type in brackets, [string]. Unlike regular PowerShell, all properties must be strongly typed.

Let’s create, or instantiate, a new variable from our class (after highlighting the class definition and using F8 or F5 to get it into memory).

$twit = [Twitterer]::new()

This syntax may look a bit odd, so let me explain. When we created our class we defined a single property. Anytime we define a class, though, PowerShell adds extra properties and methods behind the scenes.

One of those methods is new. New is a static method that can be called without the need to instantiate a new object, which is fortunate as it is the way we get new objects from our class.

To call a static method, we use the name of the class in brackets, followed by two colons, then the name of the static method. In PowerShell, to call a method you always have to use parenthesis after the name of the method even if it takes no parameters. This is unlike a regular function in PowerShell.

Finally, we assign our newly instantiated object to the variable $twit.

We can now access the properties (and methods) in our object by using what is formally known as dot notation. If you’ve done any PowerShell coding then you’ve likely used it a million times by now without realizing it had a formal name.

You simply use the name of our object, a period, then the name of the property, as in $twit.TwitterHandle. Of course if we run this right now, we won’t get anything back. This is because our variable is empty when the class is created. So let’s assign it a value.

$twit.TwitterHandle = 'ArcaneCode'
$twit.TwitterHandle

Result:

ArcaneCode

It’s that easy, we can use it like any other variable. Note one thing, when we created the property we used the $ in front of the variable. But outside the class when we reference it as a property the $ is omitted.

Default Values for Properties

There will be many times when you write a class in which you want to have some, or perhaps all, of its properties already populated with values. This will make it easier for your end user, especially for properties where the majority of the time the user can get by with the default value.

Creating a default value is simple, when you create the property you simply assign it a value.

class Twitterer
{
  # Create a property
  [string]$TwitterHandle

  # Create a property and set a default value
  [string]$Name = 'Robert C. Cain'
}

Here a second property, Name, has been added. After its declaration I simply assigned it a name (mine in this case) just like I would assign any value to a variable.

Now let’s create a new instance and examine the value in our Name property.

$twit = [Twitterer]::new()
$twit.Name

Result:

Robert C. Cain

Of course just because we’ve provided a default value doesn’t mean we can’t change it.

$twit.Name = 'Mr. Code'
$twit.Name

Result:

Mr. Code

Our First Method

Now that we’ve added properties, it’s time to add a little functionality with our first method. A class method in PowerShell works just like a function, only without the need for the function keyword. For this example, we’ll add a new method that takes the value in the $TwitterHandle property and return the URL to that handles Twitter page.

class Twitterer
{
  # Create a property
  [string]$TwitterHandle

  # Create a property and set a default value
  [string]$Name = 'Robert C. Cain'

  # Function that returns a string
  [string] TwitterURL()
  {
    $url = "https://twitter.com/$($this.TwitterHandle)"
    return $url
  }

}

The URL to a users Twitter account is simple, it is just twitter.com followed by the users twitter handle. Now, you might think you could just use $TwitterHandle to create this, but not so.

We need to let PowerShell know to use the TwitterHandle for this particular object. That’s where the $this variable comes into play.

$this is a built in variable which simply means "the current object I am running this code in". Using $this, I can reference any property or other method within this instance of my class.

I also want to point out that after the name of our method we added parenthesis. This is an indicator to PowerShell we are defining a method and not a property. In this case we are not passing in any values to our method, so they are empty. It is possible though to pass values in, which we’ll see in a future post.

Finally, note that my function, just like properties, is strongly typed. Since my URL is in the form of a string, I used [string] to indicate the data type being returned by this function.

$twit = [Twitterer]::new()
$twit.TwitterHandle = 'ArcaneCode'
$myTwitter = $twit.TwitterURL()
$myTwitter

Result:

https://twitter.com/ArcaneCode

No Return

In my previous example, our method returned a value. There will be cases though when you simply want your method to do something, and not return any values. For those times, we can use the return type of void.

class Twitterer
{
  # Create a property
  [string]$TwitterHandle

  # Create a property and set a default value
  [string]$Name = 'Robert C. Cain'

  # Function that returns a string
  [string] TwitterURL()
  {
    $url = "https://twitter.com/$($this.TwitterHandle)"
    return $url
  }

  # Function that has no return value
  [void] OpenTwitter()
  {
    Start-Process $this.TwitterURL()
  }

}

I’ve added a new method, OpenTwitter. Before it I used [void] to let Twitter know this particular method won’t be returning any data.

Within the function I call the PowerShell cmdlet Start-Process. This cmdlet will take the value passed into it and attempt to run the application that corresponds to it. For example, if I had passed in the file name to an Excel spreadsheet, PowerShell would have attempted to launch Microsoft Excel and open that file.

In this case we’re passing in a URL, so PowerShell will launch your default browser and open the Twitter webpage for that user.

Also note we used the $this built in variable to call the TwitterURL method for this current instance of our object, here $twit.

To run it we only need to call our method.

$twit = [Twitterer]::new()
$twit.TwitterHandle = 'ArcaneCode'
$twit.OpenTwitter()

If all went well your web browser should open to the Twitter page for the associated user held in the $TwitterHandle variable.

Conclusion

In this opening article we covered some of the basics of using classes in PowerShell. Even with this limited information you should be able to start creating useful classes. In future articles we’ll dive deeper into using classes in PowerShell.

I want to mention, as I write this in December 2021, that my posts for the rest of the year will diverge as I want to give a little gift and share some of my favorite things I’ve found on the internet this year. I’ll pick this series back up in January of 2022.

The demos in this series of blog posts came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Fun with PowerShell Enum Flags

Fun with PowerShell Enum Flags

Introduction

In my last two posts, I introduced the concept of Enums in PowerShell, then got into some of the more advanced uses. In this post we’ll examine a special way to use an enum, known as a Flag.

First let me mention that for all of the examples we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.2, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

A Brief Refresher on Binary Math

In order to understand how flags work you need at least a basic understanding of binary math. In this section I’ll see if I can’t provide a short, simple refresher on the subject.

In my previous article, I mentioned that I am a ham radio operator, and am a member of multiple clubs. In a small club it’s not unusual to hold multiple offices, for example I’m both the secretary and the webmaster for one of the clubs, as well as a paid member. We can denote this by using a single variable to hold this information through the use of an enum flag.

A flag is a single variable that can be broken into its individual bits to indicate multiple values. In our example, we’ll use a flag to indicate a member’s paid status, their office, and if they hold more than one position in the club, all with a single variable.

Let’s say we have six people standing in a row. Each person has a sign, the first reads "paid", the rest have the names of club offices.

When a member walks into a room, people hold up signs that indicate the person’s status in the club, while the others leave their signs face down. When the Vice President walks in, the paid sign is raised up, as is the Vice President sign. We then take a photograph to capture this information in a single place.

I happen to be both Secretary and Webmaster of my club, as well as a paid member, so in my case three signs would go up and be captured in a photo. If we happen to have a visitor to the club, none of the signs will be raised, and a photo will record that.

Bit flags work the same way. Each sign is a bit, and the photo corresponds to the variable that holds all the bits.

Let’s say we have a 32 bit integer. If all 32 of the bits are set to a 0, then the value of that integer will be 0.

If the bit in position one is set to 1, and all of the other bits are 0, it indicates the value of the variable is 1.

In the second bit position, if the value is set to 1 and all other bits set to 0, the integer value is 2. If both bits one and two are set to 1, the integer value will be 3, and so on.

This chart of binary numbers and their decimal counterparts may help clarify.

Binary Decimal
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 10

These are just the first few as an example, you could continue this chart into the trillions of values if not higher.

Should you need a further refresher on binary numbers, I’d suggest the Binary Number article on Wikipedia as a good guide. It’s important to understand binary values in order to fully understand how flags work.

Enum Flags

Let’s create our own enum flag to hold the status of club members. You declare an enum as a flag by placing the [Flags()] modifier in front of the enum declaration, as you’ll see below. Note that the values must correspond to the integer value if a bit is set. The Wikipedia article includes a nice chart that shows a decimal number and what that number looks like in binary.

[Flags()] enum MemberStatus
{
  Paid = 1
  President = 2
  VicePresident = 4
  Secretary = 8
  Treasurer = 16
  Webmaster = 32
}

I could add more to this list if needed, using the value of 64 for the next member status, then 128, then 256, and so on.

Now lets represent a member status in a variable to show a member is the Vice President, and is also a paid member. To do so, we simply add the various statuses together.

$memStatus = [MemberStatus]::Paid + [MemberStatus]::VicePresident

$memStatus

Result:

Paid, VicePresident

What’s nice about using an enum flag is that when we display the variable PowerShell converts the flags back into the members from the enum.

We could also simply assign the total number. In this case, Paid (value of 1), plus Vice President (value 4), adds up to 5.

$memStatus = [MemberStatus] 5
$memStatus

Result:

Paid, VicePresident

Finally, if we want to display the numeric value behind our flag, we can cast it as an int.

[int]$memStatus

Result:

5

Is the Flag Set? HasFlag to the Rescue!

Often you will want to see if a specific flag is set, for example we want to see if a member is paid. Now, if the paid status is the only flag set, it’s easy, just use $someVariable -eq [MemberStatus]::Paid.

It gets much more complex if a variable has multiple flags set. Fortunately, enums have a method built in called HasFlag you can use to test with.

First, let’s load a variable with several flags from our MemberStatus enum.

$memStatus = [MemberStatus]::Webmaster + [MemberStatus]::Secretary + [MemberStatus]::Paid

$memStatus

Result:

Paid, Secretary, Webmaster

So now we’ve got our $memStatus variable loaded with multiple statuses. Also note that even though we added the status in reverse order, they are always returned in ascending order from the enum declaration.

Now we want to know if our secretary / webmaster has paid their dues for the year. To do so, we’ll call the HasFlag method of our variable, and pass in the status we wish to check.

$memStatus.HasFlag([MemberStatus]::Paid)

Result:

True

The GetHashCode Method

So far, when we’ve wanted to see the value of our enum derived variable, we’ve used [int] to cast the variable in integer form.

$memStatus = [MemberStatus]::Webmaster + [MemberStatus]::Secretary + [MemberStatus]::Paid

[int]$memStatus

Result:

41

This shortcut works, and is something I’ve seen in many blog posts and examples. However, there is a method that is more clear in terms of code self-documentation. Like using [int], it will return an unsigned, 32 bit integer: GetHashCode.

$memStatus = [MemberStatus]::Webmaster + [MemberStatus]::Secretary + [MemberStatus]::Paid

$memStatus.GetHashCode()

Result:

41

Both methods work, but in my opinion GetHashCode is clearer in terms of intention, especially to someone unfamiliar with enum flags. Whichever route you go I suggest being consistent throughout your code.

Conclusion

This article focused on the use of enums as flags. While it is not something I use frequently, enum flags can be extremely useful when an item can have multiple states simultaneously. Our club member status is one such example, another is file attributes. A file could have both the hidden and compressed attributes.

Enum flags can reduce the size of your data for an item. Rather than having six individual variables for the six member statuses, a single variable can hold them all. This reduction in the size of your data can be even more valuable when that data is being stored in a database or file.

The demos in this series of blog posts were derived from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

More Fun with PowerShell Enums

Introduction

In a previous post, Fun with PowerShell Enums I introduced the concept of Enums.

In this post we’ll dive deeper into enums, taking a look at more of its properties a well as other ways to use enums.

First let me mention that for all of the examples we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.2, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Enums for Code Clarity

One major way enums can be used is to clarify your code. In my previous post on enums I mentioned I was a ham radio operator. The clubs I belong to meet on alternate Thursday nights. Let’s say I wrote a small PowerShell function to let me know if tonight is a ham club meeting.

Into that function I need to pass one parameter, a number that indicates the day of the week. If 0 is Sunday, and 6 Saturday, the number 4 represents a Thursday.

function IsItHamClubNight($Day)
{
  if ($Day -eq 4)
  { Write-Host "Yay! It's ham club night" }
  else 
  { Write-Host "Sorry, just a boring night" }
}

When I call this function, I have to know what number to use.

$day = 4
IsItHamClubNight $day

Result:

Yay! It's ham club night

Obviously it would be easier to pass in the name of the day of the week rather than a number. But this function is now heavily embedded in your organization, changing it would require a large effort.

By using an enum, we can provide the ability to use a human readable name, without the need to rewrite our function.

Enum DaysOfWeek
{
  Sunday = 0
  Monday = 1
  Tuesday = 2
  Wednesday = 3
  Thursday = 4
  Friday = 5
  Saturday = 6
}

Enums allow us to assign a value to each label. Here we made Sunday 0, and so on, but we can use any integer value. Now we can assign one of the enums to a variable and pass that into our function.

$day = [DaysOfWeek]::Thursday
IsItHamClubNight $day

Result:

Yay! It's ham club night

Even better, we can skip the use of a variable.

IsItHamClubNight ([DayOfWeek]::Thursday)

Which gives the same result. Now users of your function don’t have to remember which number represents Thursday, they can simply use the name of our enum followed by the day of the week. All of this without the need to modify our IsItHamClubNight function!

Getting the Enum Values

Let’s say you know the enum you want to use is DaysOfWeek, but you can’t quite recall the various day names. Was it Monday, or the short abbreviation Mon? Or maybe you just want the full list so you can iterate over them.

The Enum type has a method, GetEnumNames. It can be used to retrieve the members of the enum.

[DaysOfWeek].GetEnumNames()

Result:

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

It actually returns a collection so you can use it to iterate over the members, as in a foreach loop.

foreach( $enumValue in [DaysOfWeek].GetEnumNames() )
{
  Write-Host "Enum Value is $enumValue"
}

Result:

Enum Value is Sunday
Enum Value is Monday
Enum Value is Tuesday
Enum Value is Wednesday
Enum Value is Thursday
Enum Value is Friday
Enum Value is Saturday

Alternatively you can pipe it, for example into a ForEach-Object.

[DaysOfWeek].GetEnumNames() |
  ForEach-Object { "{0} {1}" -f $_, [int]([DaysOfWeek]::$_) }

Result:

Sunday 0
Monday 1
Tuesday 2
Wednesday 3
Thursday 4
Friday 5
Saturday 6

This looks a bit cryptic so let me break it down. The "{0} {1}" -f indicates we want to create a formatted string. The {0} and {1} are placeholders. After the -f is a list of values. The first value will go into the {0}, the second into the {1}.

The next thing you see is $_. This is simply a PowerShell shortcut for "the current object coming through the pipeline". From the enum, Sunday will be first, then Monday, and so on.

Next you see [int]([DaysOfWeek]::$_). The [int] is used to convert what comes after it into an integer value. Next, we access the DayOfWeek enum, and give it the current object.

As a result, the output displays both the name from the enum, as well as the value associated with it.

If you want to learn more about string formatting, I’ll refer you to my post Fun With PowerShell String Formatting.

Enums with Duplicate Values

It is possible to assign the same numeric value to multiple items in an enum. For each position in our radio club, we want to indicate their level. President and Vice President are at the top, with Secretary and Treasurer in the second tier. Finally there are some appointed positions that are important, but not the top of the chain.

Here’s how this might be expressed in an enum.

Enum ClubPositions
{
  President = 1
  VicePresident = 1
  Secretary = 2
  Treasurer = 2
  Webmaster = 3
  Greeter = 3
  SnackBringer = 3
}

We can do comparisons between our various offices and their associated numeric value.

[ClubPositions]::President -eq 1
[ClubPositions]::VicePresident -eq 1

Result:

True
True

You can even compare two enums to each other.

[ClubPositions]::President -eq [ClubPositions]::VicePresident

Result:

True

Remember the GetEnumNames method we looked at a moment ago? This works as well.

[ClubPositions].GetEnumNames()

Result:

President
VicePresident
Secretary
Treasurer
Webmaster
Greeter
SnackBringer

There is one other method very similar to GetEnumNames, GetEnumValues. It doesn’t work quite like you’d think though.

First, let’s use it with our DaysOfWeek enum.

[DaysOfWeek].GetEnumValues()

Result:

Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday

As you can see, there’s no real difference compared to GetEnumNames. But now let’s run it for the ClubPositions enum.

[ClubPositions].GetEnumValues()

Result:

VicePresident
VicePresident
Treasurer
Treasurer
Greeter
Greeter
Greeter

In the second example it went through the enum, and only returned one text value for each integer. This is why we only see one entry for each numeric value.

It actually does the same thing with the DaysOfWeek enum, but because we only used each integer value once, only one label for each value was returned.

Conclusion

Using enums to aid with code clarity was the first item in this blog post. We then saw how to assign values to the individual members of an enum, as well as how to iterate over the members of an enum.

In the next article in this series, we’ll look at the concept of using enums as bit flags for when you need to save multiple states for a single item.

The demos in this series of blog posts were derived from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Security for Apartment Dwellers

Introduction

I’m at the stage in my life where my wife and I are becoming empty nesters. My youngest daughter Anna is moving several states away to start a new life and I couldn’t be prouder of her.

As she’s been packing I’ve shared some security advice she can use at her new apartment. I got to thinking "hey, this is good stuff I should share it with others!" Next week I’ll continue my series on PowerShell Enums, but for this week let’s talk security.

By the way, this advice can apply to apartment dwellers, dorm rooms, or even rental houses. For simplicity I’ll refer to these as your home in this article, meaning any place you live in and rent.

The Need for Security

Whenever you rent, you are in someone else’s property. That means they too have keys to your dwelling.

And they use them. Exterminators come in on a regular basis to spray for bugs. Folks from the maintenance crew come in to check smoke alarms, air conditioning filters, and more.

Now let me be clear, I firmly believe that 99% of these people are good, hard working, and honest. But all it takes is that one bad egg to ruin your day, maybe even your year.

Some places provide notification in advance that someone will be entering your place of residence. But not all places, back when I was a renter it wasn’t unusual to come home and find a "your friendly neighborhood exterminator was here today" note on my door.

Or you may not know at all, one complex I lived in never told you, I only knew if a neighbor mentioned it.

A quick disclaimer before we get started: I mention several products in this post. These are not ads, I’m not making any money from these endorsements. I just like them and paid my own hard earned cash for them.

So that said, let me get into the suggestions.

Computer Security

Desktops

If you have a desktop computer, you should always lock your screen before you leave home. By locking your computer you’ll require the entry of a password or pin to use the computer. Most people keep all types of things on their computer.

Web browsers are often set to automatically login to email, financial, even gaming accounts. Family photos populate your drive. Important documents like tax returns are often scanned and stored on your hard drive.

On all operating systems there will be menu options to lock the screen, but there are also keystroke shortcuts that will allow you to quickly lock your computer.

On Windows, the Windows Key + L combination will lock the screen. This frequently works on many Linux distributions as well, although you should check your documentation to be sure.

On macOS, you can use the Ctrl + Command + Q key combination to lock the screen.

If you are on macOS, and have an iPhone, there’s a nifty app called NearLock. Actually it is two apps, one runs on your Mac, the other on your iPhone.

When your phone gets more than 3 feet away (you can change the distance in your configuration) it locks your Mac. It’ll also unlock your Mac when you get back into range.

I can’t stress how important this one tip is, because this is the situation where someone could steal from you and you wouldn’t know it. A bad guy could copy your personal info onto a USB key, and you’d be none with wiser.

Laptops – Cable Lock

If you leave your laptop turned on when you leave home, then follow the advice for desktops about locking your screen.

I’d also suggest getting a cable lock. This Kensington lock, found on Amazon is a good choice that I use, but there are many options.

Almost all laptops have a small slot the end with the lock will fit into, with the possible exception of some of the very thin laptops such as some recent MacBooks. Check your laptop to be sure before ordering.

Make sure you have a strong, secure spot to loop the cable through. A desk leg that you can just pick up and slip off the cable is a poor choice.

Some locking cables come with an adhesive hook you can use, but I don’t trust those. With just a little effort many can be easily ripped or pried off. But it is better than nothing.

Instead of the adhesive hook I suggest going to your local hardware store and getting an eye bolt with the hole big enough to get the cable through, or perhaps a handle that would go on a chest or garage door. Screw it into your desk, or even better the wall (assuming that doesn’t violate your lease).

Cable locks come in two types, a combination lock and one with a key. They key is faster to unlock, but if you are the kind of person who leaves their keys by the front door the combination may be more convenient.

The combination has another advantage if you share a laptop with your spouse or other family member. It’s easy to share the combination with other trusted people.

Note that many desktop computers these days also have the ability to have a cable lock. If not, you may be able to bolt a secure hook to yours. In addition to cable locks they also make cables with just loops on both ends such as this one from Amazon. Slip one end through the hook, then use a good heavy duty padlock to connect the loops.

Laptops – Lock it up

Another way to secure your laptop is to get a small, two (or more) drawer filing cabinet that has a lock on it. Plenty of space to store one or more laptops in.

A nice bonus is the ability store other valuables in it. Perhaps you have some nice camera equipment, portable gaming gear like a Nintendo Switch, and iPads or Android tablets.

Anything small but expensive could be placed in your file cabinet. I’ll admit, a determined thief could just carry off the whole file cabinet, or your desktop.

The security tips in this article are more geared toward the opportunist thief, ones who didn’t set out to take anything but when the opportunity arises they jump on it.

If you really wanted to carry it to an extreme, you could attach eye bolts or something similar to the file cabinet, desk, even the wall, then connect them using a steel cable with loops on either end like the one I suggested in the previous section. Use a heavy duty padlock to hook them all together. It will make the whole collection to big, heavy, and unwieldy to simply carry away.

Mail Call

If it wasn’t for junk mail I wouldn’t get any mail at all!

Well not quite, in addition to the stack of junk mail I still get bills (despite my best efforts to go paperless). These bills often have account numbers or enough information for a crook to hijack your accounts.

In my pile of junk mail I get credit card offers or "take out a loan with us with the low interest rate of 53%!" Of course this is annoying, but can also be dangerous as someone could take out a loan or credit card in your name, but changing the address to them.

Keep these secured in your file cabinet (you did buy one for your laptops, tablets, and other expensive stuff didn’t you?). One stack for junk, the other for bills and other info to retain.

You should always take time to shred junk mail with monetary offers, as well as bills when you are done with them. (Obviously you’ll also want a shredder to go with this setup.) If you want to keep copies then you can get printer/copier/scanners at reasonable prices and store on your computer. You know, the one you lock everytime before you leave home.

If you don’t want a scanner, just take pictures of these items with your phone. On my iPhone I use an app called Scanner Pro.

Not only does it take the picture but it also handles things like skewed pics, making the document nice and square (well rectangular for pieces of paper). If I’m only scanning in one or two pages, I use Scanner Pro rather than going to my multi-function printer.

I highly recommend getting an app like this for your phone. Feel free to post a comment with your favorite app, especially if you are an Android user.

Cold Hard Cash

I believe it is useful to keep a bit of cash on hand. You might lose or have your credit/debit card stolen and have to wait for a replacement. Perhaps there is an extended power or internet outage, and cash is the only way to purchase supplies.

Never leave cash laying around. Most crooks, even the casual opportunist, knows to check under the mattress or the underwear drawer in your dresser.

Use the file cabinet, or get a small safe. If you carry a purse, but sometimes leave it at home, maybe to go jogging, swimming, or other exercises, secure it in your file cabinet or safe when you are gone.

If you normally carry a wallet, but leave it behind for exercise or other reasons, lock it up as well.

Conclusion

After reading this you may think I’m a little paranoid. But remember, just because you’re paranoid doesn’t mean they’re not out to get you!

Most of these suggestions can be had for little cost, plus a few seconds of time, but can save you a lot of headaches and money in the long run. All it takes is one incident to ruin your credit, put you in debt, and deprive you of valuable, daily used tools like laptops and tablets.

Fun with PowerShell Enums

Introduction

This post begins a series on using Classes in PowerShell. As a first step, we will cover the use of an Enum, as enums are frequently used in combination with classes.

An Enum is a way to provide a set of predetermined values to the end user. This allows the user to pick from a finite list, and assure a value being passed into a function or class will be valid.

We’ll take a deeper look in a moment, but first let me mention that for all of the examples we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.2, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Basic Enum Declaration

Enum is short for enumerated value. As mentioned in the intro, it is a set of predetermined values that will ensure users of your script select a valid value required by your PowerShell code. Let’s start by defining a basic Enum.

Enum MyTwitters
{
  ArcaneCode
  ArcaneTC
  N4IXT
}

As you can see, the basic declaration is very simple. You simply use the keyword Enum followed by what you wish to name it. In the squiggly braces you list the valid values.

Here I’ve listed three of my Twitter accounts. The first is the main one I use, ArcaneCode. The second is the one I use for my company ArcaneTC (short for Arcane Training and Consulting). I use it primarily to announce new Pluralsight courses, so it doesn’t see a huge amount of use.

One of my hobbies is amateur radio, also known as ham radio. N4IXT is my FCC assigned amateur radio call sign I use to identify myself on the air. I don’t post a lot, I use it mostly to read through the latest news in the ham radio world.

Note that Enums cannot have spaces in their names, although you could use separators such as an underscore. Arcane_Code would be a valid value for an enum.

What are my valid Enum values?

You’ve now created an Enum, perhaps you’ve included it within a module you are providing to other programmers in your company. How can they retrieve a list of valid values?

Hopefully you’ve provided documentation, but it’s also easy for a user to have PowerShell return a list of values. First, make sure you have executed the code above by highlighting it and using F8 (VSCode) or F5 (PowerShell IDE) to get the Enum into memory. Then you can run the line of code below.

[MyTwitters].GetEnumNames()

Result:

ArcaneCode
ArcaneTC
N4IXT

As you can see, it simply returns a list of the values that we declared in the Enum.

Assigning an Enum to a Variable

Now we have our enum, and know what the values are. We’re now ready to use our enum in our script. Here I’ll just assign it to a variable, but we could also pass an enumerated value into a function.

Begin typing out the following code sample, and note what happens when you hit the second colon.

$tweet = [MyTwitters]::

When you have entered the second colon, you should see a list of the enumerated values in VSCode.

I say should as sometimes I’ve had VSCode return enums that were declared in my script, and not for the specific enum I was working with.

In the PowerShell ISE though, I’ve had it work right every time.

When complete, your assignment should look like:

$tweet = [MyTwitters]::ArcaneCode

Is it Valid?

So you have a value from the enum copied into your variable, $tweet. How do we test it?

It’s important to understand enums are objects. In addition to the values you provide they have a set of properties and methods you can use. In the previous example, you saw the GetEnumNames method being used.

Another useful method is IsDefined.

[enum]::IsDefined(([MyTwitters]), $tweet)

Result:

True

Into the IsDefined method you pass in your enumeration, then the value you want to test. Here our value is in the variable $tweet. If the value is contained in the enum, the method returns True.

What if the user passes in a value that is not contained in our enum?

$tweet = 'Invalid'
[enum]::IsDefined(([MyTwitters]), $tweet)

Result:

False

Returning False makes it easy to use an if statement and raise an error if the user tries to use an invalid value. For more on the if statement, see my post Fun with PowerShell Logic Branching.

Conclusion

For these examples we used my Twitter accounts for our enum values, but there are many more uses some of them extremely common. You could load an enum with the days of the week, months of the year, colors, and other common values your scripts might use.

In the introduction I mentioned we are starting our series on classes with the enum as enums are frequently used with classes. However this is not a requirement. You can use enums with any PowerShell code you want to write.

In the my next post we’ll continue exploring the enum. We’ll look at a few more useful methods, as well as see how to assign values to our enum values.

The demos in this series of blog posts came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.

Solved: CMD Key Combos Not Working with Logitech K850 and MacOS Monterrey

Earlier this year I did a blog post, Working From Home – Permanently, in which I recommend using a good keyboard especially when you have multiple computers.

Since upgrading to MacOS Monterrey I’ve had an issue where some of the basic command key combos, such as CMD+X, CMD+V, CMD+C, and more were not working from my Logitech K850 keyboard. However, when I press those keys directly on my MacBook Pro they worked fine.

For those unfamiliar with it, the Logitech K850 will let you bluetooth connect to three different computers. It has three buttons labeled 1, 2, and 3 that will switch the input to a different computer.

This seemed to occur when I first powered up my MacBook. I’d go to do something and find my often used command key combos (CMD+C, etc) would not work.

The fix turned out to be fairly simple, what I needed to do is switch the input to another computer (using the 1, 2, 3 buttons). Once the keyboard was connected to another machine, I could return to my MacBook and find that the CMD keys worked like they were supposed to.

I’m guessing the K850 must power up in some default state in which it doesn’t realize it is in “Mac” mode. It isn’t until you switch from some other computer to the MacBook that it realizes “oh, hey, I’m connected to a MacBook so I’ll switch to Mac mode” and make the CMD key combos work right.

But that’s just a guess on my part, the important thing is if you are having the same issue, just switch the keyboard input to a different computer then back to the MacBook via the 1, 2, 3 buttons and the CMD key combinations should start working.

Note, in my testing I had to switch to an input that was active (i.e. to a computer that was powered up). When I switched to an unused input (not currently connected to a powered computer) and back it didn’t always work right.

No Fun with Slow Internet and Big Downloads

I’m taking this rare opportunity to post a bit of a rant.

I live in a rural part of the country. It’s a beautiful area, lots of woods, nature, a very quiet area.

With that comes some downsides, including slow internet. My home speed is a blazing twelve megabits. I have a relative’s house I work at in another part of the state, there the internet is a mere three megabits.

At the same time, software updates seem to be growing larger and larger. The most recent update to Apple’s XCode was over twelve gig. There is a video editing package called DaVinci Resolve that regularly puts out two gig updates.

These take incredibly lengthy periods of time to download at my home, assuming the connection doesn’t drop or reset mid-download. I wind up going to coffee shops or the library where there is faster internet that allows me to receive these large updates. Even in these locations the fastest speed is one hundred megabits, shared among all its users.

I’m not the only person in this situation. At conferences (back in the pre-COVID days when we had them) I often spoke with other attendees who lived under similar circumstances.

Of course, the real solution is to get faster internet to our rural communities, both here in the US and worldwide. Much of our planet is dependent on the internet for communications, business, and more, to the point where it is becoming a necessity.

Unfortunately, infrastructure is not cheap, nor is it quick to roll out. So, until that happens, I’d really like for software makers to remember those of us with slower connections.

Instead of multi-gigabyte updates, I’d love to see software makers create smaller patches for their software, instead of a basic complete reinstall of the applications. Yes, it would require more testing, but would result in lower demands on their corporate servers and bandwidth.

Perhaps if others across the planet joined our voices it may have a positive effect, both in reducing download sizes and in getting a meaningful truly high-speed internet infrastructure in place.

Fun With PowerShell Providers

Fun with PowerShell Providers

Introduction

Providers are an interesting concept in PowerShell. A provider allows us to use a standard method to communicate with different areas of your computer using the same set of commands. For example, the file system is accessed using a provider. When you use Get-ChildItem it goes through the file system provider to return a list of the files on your computer.

We’ll take a deeper look in a moment, but first let me mention that for all of the examples we’ll display the code, then under it the result of our code. In this article I’ll be using PowerShell Core, 7.1.5, and VSCode. The examples should work in PowerShell 5.1 in the PowerShell IDE, although they’ve not been tested there.

To run a snippet of code highlight the lines you want to execute, then in VSCode press F8 or in the IDE F5. You can display the contents of any variable by highlighting it and using F8/F5.

Listing the Providers

To start with, let’s get a list of the available providers. To do that, PowerShell has the Get-PSProvider cmdlet.

Get-PSProvider

Result:

Name         Capabilities                        Drives
----         ------------                        ------
Registry     ShouldProcess                       {HKLM, HKCU}
Alias        ShouldProcess                       {Alias}
Environment  ShouldProcess                       {Env}
FileSystem   Filter, ShouldProcess, Credentials  {C, D, E, H…}
Function     ShouldProcess                       {Function}
Variable     ShouldProcess                       {Variable}
Certificate  ShouldProcess                       {Cert}

As you can see, there are a variety of providers available out of the box. The default provider is the FileSystem. As stated in the introduction, when you use Get-ChildItem it goes through the FileSystem provider to get a list of files, or more specifically file system objects.

In the right most column of the output, you can see a list of drives. Using the drives we can navigate the provider. To see a detailed list of drives, you can use the Get-PSDrive cmdlet.

Get-PSDrive

Result:

Name           Used (GB)     Free (GB) Provider      Root                 CurrentLocation
----           ---------     --------- --------      ----                 ---------------
Alias                                  Alias
C                 898.79         53.83 FileSystem    C:\                  \Demo\PSCore-QuickStart
Cert                                   Certificate   \
D                 953.72          0.02 FileSystem    D:\
E                 875.38         56.00 FileSystem    E:\
Env                                    Environment
Function                               Function
HKCU                                   Registry      HKEY_CURRENT_USER
HKLM                                   Registry      HKEY_LOCAL_MACHINE
Variable                               Variable
WSMan                                  WSMan

The Name column shows the name we will use when we want to change our location. First look at the column Provider, then at the rows with FileSystem. It shows three drives, C, D, and E. These are the three hard drives on my computer.

The CurrentLocation shows where we are in the provider tree. In the FileSystem provider, these locations are folders. For the C drive, I happen to be in the \Demo\PSCore-QuickStart folder.

Let’s look at how to use some of the other providers.

The Environment Provider

To change to a different provider, you simply use Set-Location followed by the name to move to, just as you would to change to a different hard drive.

Set-Location env
Get-ChildItem

Result:

Name                           Value
----                           -----
__COMPAT_LAYER                 DetectorsAppHealth
ALLUSERSPROFILE                C:\ProgramData
APPDATA                        C:\Users\arcan\AppData\Roaming
CHROME_CRASHPAD_PIPE_NAME      \\.\pipe\crashpad_7700_VQTNLEXXNDEMJHTN
COLORTERM                      truecolor
CommonProgramFiles             C:\Program Files\Common Files
CommonProgramFiles(x86)        C:\Program Files (x86)\Common Files
CommonProgramW6432             C:\Program Files\Common Files
...list truncated for brevity...

This time Get-ChildItem recognized it was operating in the context of the Environment provider, and returned a list of environment variables and their values. (Note I’ve shortened the output for brevity.)

We can access these like any other collection.

$envVars = Get-ChildItem
$envVars[1].Name
$envVars[1].Value

Result:

ALLUSERSPROFILE
C:\ProgramData

Let’s look at another provider.

The Variable Provider

Another useful provider is the Variable provider. It gives access to a list of all variables and their values currently in memory. This includes both user defined variables and built in PowerShell variables. In this example I’ll create a new variable, $aVariable. I’ll then move to the variable provider and list them.

$aVariable = 'Some Value'
Set-Location variable
Get-ChildItem

Result:

Name                           Value
----                           -----
?                              True
^                              Set-Location
$                              Get-ChildItem
args                           {}
aVariable                      Some Value
ConfirmPreference              High
DebugPreference                SilentlyContinue
...list truncated for brevity...

This returns both the names and values for all of the variables. This can be an excellent debugging tool, for example logging all values when an error occurs.

Other Providers

In addition to the built in list of providers you have seen, many modules will add their own providers that you can navigate. On of my favorites is the SQL Server module.

I’ll go over it more in a future post, but know that through it you can use Get-ChildItem to navigate your list of servers, instances, databases, tables, and columns all as if they were your file system.

You will find many modules supply providers you’ll find useful.

Conclusion

In this post we took a brief look at providers, and how to navigate them. In addition, you are now aware there is a big world of providers outside the few default ones you saw in this post.

The demos in this series of blog posts came from my Pluralsight course PowerShell 7 Quick Start for Developers on Linux, macOS and Windows, one of many PowerShell courses I have on Pluralsight. All of my courses are linked on my About Me page.

If you don’t have a Pluralsight subscription, just go to my list of courses on Pluralsight . At the top is a Try For Free button you can use to get a free 10 day subscription to Pluralsight, with which you can watch my courses, or any other course on the site.