The Fun With PowerShell Roundup

PSCustomObject Sample

Introduction

Since September 2020 I’ve been posting extensively about PowerShell in a series I’ve titled Fun With PowerShell. In my next post I will begin a series on a new topic, but before I do I wanted to leave with a Fun With PowerShell Roundup" post.

Below you will find a listing of all posts in my Fun With PowerShell series. Note there are other posts I’ve done in this time frame, but since they did not focus on PowerShell I’ve omitted them from this listing.

The Posts

Date Title
20-09-29 VSCode User Snippets for PowerShell and MarkDown
20-12-05 Two New PowerShell Courses for Developers on Pluralsight
20-12-14 Iterate Over A Hashtable in PowerShell
20-12-21 Fixing the Failed To Acquire Token Error When Logging Into Azure from PowerShell
21-01-04 Suppress Write-Verbose When Calling A function in PowerShell
21-07-05 Fun with PowerShell Get-Random
21-07-12 Fun With PowerShell Strings
21-07-26 Fun With PowerShell Arrays
21-08-02 Fun With PowerShell Hash Tables
21-08-09 Fun With PowerShell Logic Branching
21-08-16 Fun With PowerShell Code Formatting
21-08-23 Fun with PowerShell Loops
21-07-19 Fun With PowerShell String Formatting
21-08-30 Fun With PowerShell Basic Functions
21-09-06 Fun With PowerShell Advanced Functions
21-09-13 Fun With PowerShell Pipelined Functions
21-09-20 Fun With The PowerShell Switch Parameter
21-09-20 Fun With the PowerShell Switch Parameter
21-09-27 Fun With PowerShell Write-Verbose
21-10-04 Fun With PowerShell Write-Debug
21-10-11 Fun With VSCode Snippets for Markdown and PowerShell
21-10-18 Fun With PowerShell Providers
21-11-15 Fun with PowerShell Enums
21-11-29 More Fun with PowerShell Enums
21-12-06 Fun with PowerShell Enum Flags
21-12-14 Fun With PowerShell Classes – The Basics
22-01-10 Fun With PowerShell Objects – PSCustomObject
22-01-17 Fun With PowerShell Objects – Adding Methods to PSCustomObject
22-01-24 Fun With PowerShell Objects – Creating Objects from C#
22-01-31 Fun With PowerShell Objects – Modifying Existing Objects
22-02-07 Fun With PowerShell Classes – Static Properties and Methods
22-02-14 Fun With PowerShell Classes – Overloading
22-02-21 Fun With PowerShell Classes – Constructors
22-03-24 Fun With PowerShell – Extracting Blog Titles and Links from a WordPress Blog with PowerShell
22-03-28           Fun With PowerShell – Extracting Blog Titles and Links from a WordPress Blog with PowerShell – Generating Markdown

Conclusion

This is the wrap up post for my Fun With PowerShell series. Use it as an index to quickly refer back to posts of interest to you. These will make a good quick reference to the many aspects of PowerShell programming.

In my next blog post I’ll begin a new "Fun With…" series, so stay tuned for more fun.

All of the posts in my Fun With PowerShell series 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 – Extracting Blog Titles and Links from a WordPress Blog with PowerShell – Generating Markdown

Introduction

In my previous blogpost, Fun With PowerShell – Extracting Blog Titles and Links from a WordPress Blog with PowerShell, I described how I extracted the title, link, and publication date for posts in my WordPress blog using PowerShell. I then went on to use PowerShell to generate HTML code that I could insert into a post, or create a basic webpage.

It would also be useful to generate Markdown, instead of HTML, in case I want to use it somewhere such as my GitHub page. In this post we’ll see how to do just that, and create Markdown from the output array of PSCustomObjects.

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.2, 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.

Where to Start

Much of the work has already been done in the previous post. Review it, stopping at the Creating HTML section. The array we created will now be used in generating Markdown.

This is the reason I created an array of custom objects holding the title, link, and publication date. Just as I used it to create HTML, I can now use it to generate Markdown.

Generating Markdown

Like I did with the HTML, I created a function to create Markdown. This is and advanced function that I’ll pipeline the array of PSCustomObjects into.

function Get-WPMarkdown()
{
  [CmdletBinding()]
  param (
          [Parameter (ValuefromPipeline)] $wpObjects
        , [switch] $FormatAsTable
        )

  process
  {
    # Create a formatted output line
    if (!$FormatAsTable.IsPresent)
    {
      # Create each line as a paragraph
      $outLine = @"
$($wpObjects.PubDate) - [$($wpObjects.Title)]($($wpObjects.Link))
"@
    }
    else
    {
      # Create each line as a row in a table
      $outLine = @"
|$($wpObjects.PubDate)|[$($wpObjects.Title)]($($wpObjects.Link))|
"@
    }

    # Return the formatted line
    $outLine
  }

}

The first parameter accepts the custom objects we generated from the pipeline. The second is a switch that will format the output as a row in a Markdown table, as opposed to just a line of Markdown text.

I then check to see if the switch was passed in, and format the line to return accordingly. Finally I send the generated line out of the function.

Using the Get-WPMarkdown Function

Now all we have to do is call the function. As a reminder, the data in the $outData variable is the array of custom objects we generated in the previous posts.

$outMd = $outData | Get-WPMarkdown

$wpOutputMd = 'D:\OneDrive\BlogPosts\Markdown\arcanecode.wordpress2.md'
Out-File -FilePath $wpOutputMd -InputObject $outMd -Force

This will generate our data as rows in a Markdown file. Below is a small example.

2020-09-29 - [VSCode User Snippets for PowerShell and MarkDown](https://arcanecode.com/2020/09/29/vscode-user-snippets-for-powershell-and-markdown/)
2020-12-05 - [Two New PowerShell Courses for Developers on Pluralsight](https://arcanecode.com/2020/12/05/two-new-powershell-courses-for-developers-on-pluralsight/)
2020-12-14 - [Iterate Over A Hashtable in PowerShell](https://arcanecode.com/2020/12/14/iterate-over-a-hashtable-in-powershell/)

Outputting a Markdown Table

In the code there was a switch to format the output Markdown as a table.

$outMd = $outData | Get-WPMarkdown -FormatAsTable

As I did with the HTML example, I wanted to wrap the generated data in the appropriate Markdown code to make this a complete Markdown table. I created another function to handle this.

function Add-WPMarkdownHeader()
{
  [CmdletBinding()]
  param (
          [Parameter (Mandatory = $true)]
          $markdownData
        )

  # Create a new array
  $outTable = @()

  # Add the html to create a left aligned table header
  $outTable += '|Date|Post|'
  $outTable += '|:-----|:-----|'

  # Add the existing table row data
  foreach ($row in $markdownData) { $outTable += $row }

  # Return the output
  return $outTable
}

As you can see, it creates a new array, adding the Markdown code for a table header, one specific for our data. It then cycles through the array that was passed in and adds it to the new array. Once done this new array is returned by the function.

To call it we simply use the following sample to write it to a file.

$outTable = Add-WPMarkdownHeader $outMd
Out-File -FilePath $wpOutputMd -InputObject $outTable -Force

Here is a sample of the output.

|Date|Post|
|:-----|:-----|
2020-09-29 - [VSCode User Snippets for PowerShell and MarkDown](https://arcanecode.com/2020/09/29/vscode-user-snippets-for-powershell-and-markdown/)
2020-12-05 - [Two New PowerShell Courses for Developers on Pluralsight](https://arcanecode.com/2020/12/05/two-new-powershell-courses-for-developers-on-pluralsight/)
2020-12-14 - [Iterate Over A Hashtable in PowerShell](https://arcanecode.com/2020/12/14/iterate-over-a-hashtable-in-powershell/)

Conclusion

In this post we saw how to generate Markdown code from a WordPress blog extract. Combined with the code in my previous post I now have a handy script I can use to generate HTML and Markdown code from my blog posts. This will be handy for both now, and when I want to create wrap up posts for future series.

These techniques can be easily adapted for any XML file that you wish to create a summary listing for, in HTML or Markdown or both.

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 – Extracting Blog Titles and Links from a WordPress Blog with PowerShell

Introduction

Since September of 2020 I have been blogging heavily on PowerShell. In a few posts I’m going to start a new series on a different subject, but first I wanted to provide a wrap up post with links to all my recent PowerShell posts.

Extracting all of those titles and links by hand seemed like a labor intensive task, so of course I wanted to automate it. In addition, I’ll be able to reuse the code when I’m ready to wrap up my next, or a future, series.

My blog is hosted on WordPress.com, which provides an export function. In this post I’ll cover the code I created to extract all my links, and how I generated HTML from it. In my next post I’ll show the same methodology for generating Markdown, and in the next post will do the PowerShell roundup.

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.2, 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.

Extracting Data from WordPress

One of the administrator tools in the WordPress.com site is the ability to extract your blog. You can generate an XML file with the entire contents of your blog. This includes all of the data including the post itself, comments, and associated metadata. They do provide the ability to limit the extract by by date range and subjects.

As you can guess this extract file is large, far too much to sift through by hand. That’s where PowerShell came to my rescue!

For each post, the exported XML file has three lines we are interested in, the tags with <title>, <pubDate> and <link>. I tackled this in stages.

As the first stage, I simply loop over the data in the file, looking for the XML tags I need. When I’ve found all three, I have a small function that creates a PowerShell custom object. After each object is created, it is added into an array. I needed to do a little filtering, as over the last year I’ve added a few more blog posts on other topics. I did not want these to be included in my future "Fun With PowerShell Roundup" post.

Once I have an array of custom objects, I can easily use them in multiple scenarios. For generating HTML I created a function that takes each object and generates a line of HTML code. It also has a way to generate the line as an HTML row instead of a series of paragraphs.

For my purposes, this was all I needed. However there may be times when you wish to generate a complete, but basic, web page. There is one more function I created that will take the output of the HTML rows and add the lines needed to make it a valid HTML page.

Generating a Custom WordPress Object

I mentioned a function to create a custom object, so let’s start with that.

function Get-WPObject()
{
  [CmdletBinding()]
  param (
          [Parameter( Mandatory = $true ) ]
          [string] $Title
        , [Parameter( Mandatory = $true ) ]
          [string] $Link
        , [Parameter( Mandatory = $true ) ]
          [string] $PubDate
        )

  # Build a hash table with the properties
  $properties = [ordered]@{ Title = $Title
                            Link = $Link
                            PubDate = $PubDate
                          }

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

  # Return the newly created object
  return $object
}

The function is straightforward, it takes the three passed in parameters and creates a custom object from it. This is a common technique, it allows you to easily generate a custom object. It also leverages code reuse.

If you want to get a more detailed explanation on creating and using custom PowerShell objects, see my post Fun With PowerShell Objects – PSCustomObject.

Creating The Array

Before we create the array, we need to read in the data from the WordPress XML extract file. I create a variable to hold the location, then read it in.

$wpInput = 'D:\OneDrive\BlogPosts\Markdown\arcanecode.wordpress.2022-03-08.000.xml'

# Read the data from input file
$inData = Get-Content $wpInput

Now it’s time to read in the data from the XML file, one line at a time.

# Setup an empty array to hold the output
$outData = @()

foreach ($line in $inData)
{

  # Extract the title. Replace the XML tags with the Markdown for a link title
  if ($line.Trim().StartsWith('<title>'))
  {
    $title = $line.Trim().Replace('<title>', '').Replace('</title>', '')
  }

  # Extract the link, replacing the XML tags with the Markdown link characters
  if ($line.Trim().StartsWith('<link>'))
  {
    $link = $line.Trim().Replace('<link>', '').Replace('</link>', '')

    # For some reason the WordPress export uses http instead of https. Since the
    # blog supports https, lets fix that.
    $link = $link.Replace('http:', 'https:')
  }

  if ($line.Trim().StartsWith('<pubDate>'))
  {
    # Extract just the date, then covert it to a DateTime datatype
    $pubDateTemp = [DateTime]($line.Trim().Replace('<pubDate>', '').Replace('</pubDate>', ''))

    # Now use the ToString feature of a DataTime datatype to format the date
    $pubDate = $pubDateTemp.ToString('yyyy-MM-dd')

    # In addition to links to the blog posts themselves, the exported XML file also
    # has links to images. To weed these out, we will search for posts that have PowerShell
    # in the title. The Contains method is case sensitive so it will omit the links
    # to the images.
    #
    # When a match is found, it passes the Title/Link/PubDate to our function, which will
    # generate a custom object. This object will be added to our output array.
    if ($title.Contains('PowerShell'))
    {
      $outData += Get-WPObject -Title $title -Link $link -PubDate $pubDate
    }

  }

} # End the foreach ($line in $inData) loop

First I create an empty array that will hold the output. To learn more about arrays, see my post Fun With PowerShell Arrays.

Now I enter a foreach loop, to go over each line in the array. If you don’t know, when you use Get-Content it returns each line in the file as a row in an array. That’s what I want here, but be aware if you add the -Raw switch to the Get-Content it returns the entire file as one big text string.

The data in the XML occurs in the order of Title, Link, then PubDate. PubDate is the Publication Date for the blog post.

As I find the title and link, I remove the XML tags then copy the data into a local variable. For some reason the extract uses http for the links, so I wanted to correct it to use https.

When I find the PubDate, I wanted to reformat it as a string in YYYY-MM-DD format. I extract just the date portion of the line by removing the XML tags. I then cast it to a [DateTime] and store it in a temporary variable.

I can then call the ToString method of the DataTime datatype to format it in a format I want, namely YYYY-MM-DD (Year, Month, Day).

Next I check to see if the title contains the word PowerShell. If so, I now have the three pieces of info I need, and call my function to generate the PSCustomObject and add it to the output array.

Creating HTML

To create the HTML I wrote a function, Get-WPHtml. Like the other functions I created this as an Advanced function. To read up on Advanced Functions, see my article Fun With PowerShell Advanced Functions.

I needed this so I could pipe the data from the array containing my WordPress PSCustomObjects into it. By doing it this way, I could reuse the Get-WPHtml with any array that has objects with three properties of Title, Link, and PubDate.

Let’s look at the function.

function Get-WPHtml()
{
  [CmdletBinding()]
  param (
          [Parameter (ValuefromPipeline)] $wpObjects
        , [Parameter (Mandatory = $false)] $Indent = 0
        , [switch] $FormatAsTable
        )

  process
  {
    # Create a string with spaces to indent the code. If not used no indent is created.
    $space = ' ' * $Indent

    # Create a formatted output line
    if (!$FormatAsTable.IsPresent)
    {
      # Create each line as a paragraph
      $outLine = @"
$space<p>$($wpObjects.PubDate) - <a href="$($wpObjects.Link)" target=blank>$($wpObjects.Title)</a></p>
"@
    }
    else
    {
      # Create each line as a row in a table
      $outLine = @"
$space<tr> <td>$($wpObjects.PubDate)</td> <td><a href="$($wpObjects.Link)" target=blank>$($wpObjects.Title)</a></td> </tr>
"@
    }

    # Return the formatted line
    $outLine
  }

}

The first parameter will accept the data from our pipeline, as I explain in my article Fun With PowerShell Pipelined Functions. Next is an optional parameter that allows the user to indent each row a certain number of spaces. The final parameter toggles between formatting each row as a standard paragraph or as a table row.

The process block will run once for each piece of data passed in from the pipeline. It creates a variable with the number of spaces the user indicated. If the user didn’t pass a value in, this will wind up being an empty string.

Next we check to see if the switch FormatAsTable was passed in, then create an output string based on the users choice. For more on switches, refer to my article Fun With the PowerShell Switch Parameter.

As a final step we return the newly formatted line, which puts it out to the pipeline.

Using the New Function

Using these functions is easy. We take the array of custom objects, then pipe it into the new Get-WPHtml function using an indent of 2. The result is copied into the $outHtml variable which will be an array.

Finally we set the path for our output file, then use the Out-File cmdlet to write to disk.

$outHtml = $outData | Get-WPHtml -Indent 2

# Save the new array to a file. Use Force to overwrite the file if it exists
$wpOutputHtml = 'D:\OneDrive\BlogPosts\Markdown\arcanecode.wordpress2.html'
Out-File -FilePath $wpOutputHtml -InputObject $outHtml -Force

Creating a Full HTML Page

For my purposes, I am going to take the data in the file and copy and paste it into the WordPress post editor when I create my roundup blog post. For testing purposes, however, it was convenient to have a full webpage. With a full webpage I can open it in a web browser, see the result, and test it out. Further, in other projects I may actually need a full webpage and not the part of one that I’ll be using for my blog.

The version of the webpage with just paragraph tags will open OK in a browser, but the version of the table will not. So let’s fix that.

Here is the function I created to wrap the output of the previous function, when called using the -FormatAsTable flag, in the necessary HTML to make it a functioning webpage.

function Add-WPHtmlHeader()
{
  [CmdletBinding()]
  param (
          [Parameter (Mandatory = $true)]
          $htmlData
        )

  # Create a new array
  $outTable = @()

  # Add the html to create a left aligned table header
  $outTable += '<style>th { text-align: left; } </style>'
  $outTable += '<table>'
  $outTable += '<tr>'
  $outTable += '<th>Date</th> <th>Post</th>'
  $outTable += '</th>'

  # Add the existing table row data
  foreach ($row in $htmlData) { $outTable += $row }

  # Add the closing table tag
  $outTable += '</table>'

  # Return the output
  return $outTable
}

The one parameter is the array that was output from our Get-WPHtml function. While you can add rows to an array, or change values at a specific position, you can’t insert new rows at specific positions. As such we have to create a new empty array, which was done with $outTable.

We then add the lines needed to create the table header. For this article I’m assuming you are familiar with basic HTML tags.

Once the header rows have been added we cycle through the input array, adding each row to the new output array.

Finally we add the closing tag to finish off the table element, then return the output.

Generating the Complete Webpage

Now that the hard part is done, all we have to do is call the function, passing in the output of the previous function, stored in $outHtml. This will then be written to a file using the Out-File cmdlet.

$outTable = Add-WPHtmlHeader $outHtml

# Save the new array to a file. Use Force to overwrite the file if it exists
Out-File -FilePath $wpOutputHtml -InputObject $outTable -Force

The Output

Here is a sample of the output of our hard work. Note I’ve only included a few rows of blog posts to keep it brief.

<style>th { text-align: left; } </style>
<table>
<tr>
<th>Date</th> <th>Post</th>
</th>
  <tr> <td>2020-09-29</td> <td><a href="https://arcanecode.com/2020/09/29/vscode-user-snippets-for-powershell-and-markdown/" target=blank>VSCode User Snippets for PowerShell and MarkDown</a></td> </tr>
  <tr> <td>2020-12-05</td> <td><a href="https://arcanecode.com/2020/12/05/two-new-powershell-courses-for-developers-on-pluralsight/" target=blank>Two New PowerShell Courses for Developers on Pluralsight</a></td> </tr>
  <tr> <td>2020-12-14</td> <td><a href="https://arcanecode.com/2020/12/14/iterate-over-a-hashtable-in-powershell/" target=blank>Iterate Over A Hashtable in PowerShell</a></td> </tr>
</table>

Conclusion

In this post we tackled a project to create an HTML page based on the export of a WordPress blog. In the process we used many of the techniques I’ve blogged about over the last year and a half.

For the next post we’ll use these same techniques to create an output file in Markdown format.

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.

Getting Healthy With Tech

Introduction

Over the last few months, I’ve been working hard to get healthier. I’m diabetic, with high blood pressure, and overweight (like a lot of people in IT). So, I’ve been working hard to change that.

I’m also a tech nerd and a data guy. I’ve been using tech to track my progress, examine many critical metrics, and trend these over time.

I thought others may benefit from what I’ve done in this area over the last few months, and thought I’d share the tech and apps I’ve been using here.

Apple Watch

I use multiple platforms for my daily work, including Windows and Linux, but in my opinion it’s Apple who has health tech really nailed down. My Apple Watch is my first tool for tracking my health.

With it, I can track my exercises. Every day, no excuses, I do a minimum of thirty minutes of exercise although as I’ve progressed it’s turned into forty or more. I have an indoor exercise bike for rainy days, or on a nice day head to the great outdoors for a swift walk.

When I walk, I use walking / hiking poles to give my arms a bit of a workout. On days where I do my indoor bike, I do some weightlifting with some handheld barbells to work my arms.

My watch tracks the length of my workout, how many calories I burned, what the weather was like, and if I walk what path did I take, and what elevation change was included in my route.

In addition, it also tracks my blood oxygen level, heart rate, and has an ECG function. It also tracks my sleep to see how much rest I’m getting at night. The watch also has a cool little mindfulness app, which helps me calm down and focus.

Finally, it provides reminders to stand up every hour. Like a lot of IT people, when I get seated in front of my PC I get really focused and lose track of time. Suddenly 3 hours can go by. Then when I stand up my bad back has gone stiff, and my arthritic hips let me know they aren’t happy.

The reminder to stand every hour has really made a difference. Getting up and moving around hourly really helps eliminate those stiff and sore times.

Apple iPhone / iPad

The information in my watch feeds back to the Fitness and Health apps on my iPhone. Here I can review my information from the watch, combined with data from my other apps and tools, more of which I’ll cover momentarily.

As you can see, the fitness app gives me a nice dashboard of my progress. Today I did a 2.03-mile walk. My total exercise time for today was 50 minutes. Note that if I had done multiple exercise activities, for example 30 minutes on my bike and 10 minutes of weights, it would combine that time.

It also shows my total calories burned, along with my target for today. So far, I’ve done 440 of 600 calories for my day today. The fitness app helps you calculate your target, but you can override it. In addition, it will prompt you to increase it over time based on your past workouts.

For example, when I first started my goal was 520 calories. It then increased to 560, and now to 600. I’m sure in the near future I’ll be prompted to increase it further, although as I mentioned I can change this whenever I feel I’m ready.

Finally, it also shows how many times I’ve stood today, with a goal of standing up at least once during an hour, for 12 hours in the day.

The circles show your progress in a quick graphical format. Once the circle is closed you’ve completed your goal for the day, although it will continue the circle beyond the target. This makes it easy to challenge yourself to meet your goal.

Some refer to this as the “gameification” of exercise. Turning exercise into a game, much like trying to get a high score in a video game. While intellectually I understand what is going on, it’s still a fun challenge to meet these goals and very satisfying to see those circles close.

Beyond the software built into my Apple devices, there are some other devices and applications I use.

Basic App Requirements

Before I list the apps and devices, I wanted to list a few of my basic requirements in selecting health apps. You may not have these same requirements, so you may find other apps that work better for you.

First, the app must work on both iPad and iPhone, with bonus points if there is an associated app for the Apple Watch. I like to do my monitoring of data on the iPad (which has a nice big screen my old eyes can see) but be able to register things like taking my meds on my iPhone, which is generally handy.

Next, the app needed to sync between the iPad / iPhone. I found many good apps, but very few that had the ability to synchronize their information between devices.

Finally, it needs to be easy to use. My wife is also tracking her health, but while smart she’s not a technical person so it has to be good for an average user, and not just tech nerds like me.

Omron Blood Pressure Monitor

To keep track of my blood pressure I use a monitor from a company called Omron. They have multiple devices, mine has Bluetooth and allows for two users, which is nice as you can share with your spouse / significant other / pesky relative that won’t leave.

My model is the BP7350, but there are a range of models that support this functionality. In the Apple Appstore they have a corresponding Omron Connect app. It’s pretty simple, you take your BP on the machine, then open the app and it syncs that reading to the iPhone.

As you can see it displays my readings for today. I can tap the History button on the bottom to see my readings over time. Should my meter and phone not automatically synchronize, I can tap the Sync button in the upper right corner to have the two sync.

If you tap the + button, it brings up an additional menu. Tap on Profile, then App Settings and it will let you copy your readings into the Apple Health App.

Blood Glucose

Being diabetic it’s important to monitor my blood glucose (aka blood sugar) every day. For that, I use the OneTouch Verio Flex meter. While this meter is not in my insurance company’s “approved” list, it was only $26 (US). The test strips run about $22 (US) for thirty, about a month’s supply.

Both of these I happily pay out of pocket for the convenience of easily tracking my readings. There is a corresponding OneTouch app for the iPhone, it pairs with the meter over Bluetooth. I just take my reading and it automatically syncs to my phone.

As you can see it forms a two-way link to the Apple Health and Fitness apps. It copies my daily reading into Apple Health and reads in my workouts from Fitness. It also looks for and warns about negative trends.

And yes, before someone points it out, I know my sugars are way too high. Late last year we found out my previous meds had quit working. The doctor’s office says it happens sometimes. So, my doctor and I are working with different medications to see what is most effective for me. It’s still a work in progress.

I mentioned it is a two-way link, the app also writes my glucose numbers into my Apple Health app.

Weight Tracking

As you might expect as part of getting healthier, I wanted to lose weight. Thus, I needed an effective way to track it. Ideally, I wanted to be able to just step on a scale, and it be recorded in an app.

I already used some Wyze cameras, since I had the app already it was an easy choice to select the Wyze scale.

In addition to weight, it also has other measurements such as BMI. One tip, don’t step off the scale too soon. Let it read your weight in, then wait a second. It will then calculate its other measurements. At that point you can step off, and the readings will show up in the Wyze app.

On the screen that displays your weight, you can go into the settings (gear icon in the upper right) and turn on data sharing with third party apps, like Apple Health. At $33 (US) this was a no brainer purchase.

Hydration

Staying hydrated is important for good health. Especially for diabetics, as it helps keep the sugars flushed from your system.

Note, don’t take anything here as medical advice, I’m not a doctor, I’m just sharing what mine told me. Your situation may vary, so be sure to consult your own physician.

To track my hydration, and to get reminders that it is time to drink, I selected an app called WaterMinder. It has iPhone and iPad apps as well as an app for the Apple Watch. You enter basic data like your age, height, weight, and it calculates how much water you should take in.

To be honest this is the one failing I found with the app, the number it creates is about half of what every other site I found said I should be getting. For me it said 80 ounces a day, so I just doubled that, and overrode the goal to 160 ounces a day. Again, be sure to do your own research and discuss the proper fluid intake goals with your own doctor.

As you can see, the app provides a cute little graphic showing your intake for the day. So far, I’ve taken in 100.8 oz, or 63% of my goal. To add data, you can tap the + button and quick pick a water cup amount. Alternatively, you can tap the icon to the right of it, and it brings up a menu with various kinds of liquids and lets you type in how many ounces.

That’s one of the things I really like about this app. If you, for example, drink milk, it calculates how much water is in the milk then adds just that amount of water to your hydration total.

The app will sync between devices, but it’s not always automatic. You can force it though, although I didn’t see it documented. Just tap the + button, then tap outside it, and it will force a sync.

You can also share your readings with another user of the WaterMinder. I share mine with my wife, and she shares hers with me. We can see how much water the other one has ingested and encourage each other.

The app also has a nice history feature. It will show your trend over time, but for a given day it will also show you each individual entry. That way you can track exactly what you’d consumed that day.

Medication

Many people, as they get older, take one or more medications. Even younger, healthier folks tend to take one or more vitamins. As such, it’s important to have a way to track not just what medications you take but to remind you when it is time to take them.

I spent a lot of time trying a multitude of apps to find one that met my requirements. I finally found one called EveryDose.

EveryDose is simple to use. You enter in all your medications. Built in there is a list of valid medications, so as you begin to type you can then pick your medication from the list. Should your medication not be in the list, no problem you can elect to add it anyway.

You also enter the strength of the pill, for example 50 mg, then the dose, 1 pill, 2, 1.5 pills, etc. Like the medications, you can enter a custom value as well.

As part of the data entry, you can select a time of day to take the medication, as well as a frequency (as needed, once a day, once a week, etc.).

Note I’ve blurred out my prescription meds, but you can also enter your vitamins into the app to track them. When the reminder alert goes off, you can tell the app you took the meds on time, just now, or enter a specific date/time.

If you need to, you can go down the list and pick the meds you took individually. This is handy should you run out of a particular pill that day.

You can export your list of meds so you can easily share with your doctor or pharmacist, plus great logging so you can see which meds you have taken on what days.

The one thing it lacked was integration into Apple Health. I’d love to see it enter my vitamins and such into those areas in Apple Health. But its other features were enough to make me go with it.

Exporting Health Data

You can take your health data to the next level by exporting it. Once exported, you can add it to your own database, or most importantly share it with your health care provider.

To do that well, I found an excellent app called Health Auto Export. This is a multicomponent application. There is one app that runs on the iPhone itself. This app provides some simple reporting, but its main purpose is to run in the background and update your personal database. This data can then be used by the Health Auto Export iPad app, as well as their app that runs on MacOS.

The primary purpose is to export your health data to a variety of formats such as CSV. You can bring this into Excel or Numbers, then slice and dice to provide your doctor with just the information they need.

It also has a nice dashboard which you can customize. Here’s an example of mine:

This gives me an easy-to-use dashboard I can view on my Mac or my iPads. I can drill down, using the menu on the left, to get more details, along with trends displayed over various charts and graphs.

As I mentioned, the most important functionality for me is the ability to export data. This has allowed me to share with my doctor, which helps him adjust my medication and track my health.

Conclusion

As I work to improve my health, I’ve explored a variety of apps and tools to track my progress. I wanted to share what I’ve found so far in case you, too, are seeing to improve your health.

I said this earlier in the post but want to reiterate: I am not a medical professional, and I am not offering medical advice. Please consult your physician before embarking on any healthcare, such as exercise, hydration, medication, and the like.

For me this is a journey, a work in progress. It’s possible, even likely, that as time goes by, I will find other apps and devices to improve my health.

If you have suggestions, perhaps you’ve found a better app or device, then by all means share them in the comments so we can all get healthier. My slogan has become:

Exercise, hydrate, medicate, every day! No excuses. Be a monster!

ArcaneCode

Fun With PowerShell Classes – Constructors

Introduction

In our previous two posts, we covered the use of static properties and methods in classes, then saw how to use method overloading.

This is our final post of the series, and will cover the use of constructors. Constructors are functions that execute automatically when a class is instantiated.

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.

You may notice a backtick ` character at the end of many lines in the code samples. This is PowerShell’s line continuation character. The blog formatting has a limited width, so using the line continuation character makes the examples much easier to read. I have a section dedicated to the line continuation character in my post Fun With PowerShell Pipelined Functions if you want to learn more.

To run a snippet of code highlight the lines (or parts of a line) 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.

Starting Point

As a reminder, this is our demo class TwittererRedux as we left it at the end of the last post. We’ll start from it in this post.

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

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

  # Static Properties
  static [string] $Version = '2022.01.07.002'

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

  # Overloaded Function that returns a string
  [string] TwitterURL($twitterHandle)
  {
    $this.TwitterHandle = $twitterHandle
    $url = $this.TwitterURL()
    return $url
  }

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

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    # Note here we cannot call the $this.TwitterUrl function
    # because no object exists (hence no $this)
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

# Create a new instance and update the handle
$twit = [TwittererRedux]::new()
$twit.TwitterHandle = 'ArcaneCode'

Constructors

In the original version of our class, we created a new instance of the class by calling the ::new() static method. Then, we assigned a value to our TwitterHandle property. Wouldn’t it have been nice to do it all in one step?

Well that is possible through the use of a constructor. A constructor is a function that gets run automatically when the object is instantiated, as part of the ::new() static method. Every class gets a constructor automatically, it’s just empty.

Below is an example of our class with a constructor. For brevity I’m omitting most of the class code, and will reproduce the full class sample at the end of this post.

class TwittererRedux
{
  # Default Constructor
  TwittererRedux ()
  {
  }

  # Create a property
  [string]$TwitterHandle

  # ... rest of class goes here

A constructor is a function, with the exact same name as the class. As you can see in the sample above, TwitterRedux is both the name of the class, as well as of the function.

In this case the function is empty, it doesn’t do anything, which is what the behavior of the default constructor should be.

Having constructors allows us to create more compact code. For example, in previous examples we create a new instance of our class, then assign a handle to the TwitterHandle property on the next line. Using a constructor we can provide the ability to compress our code, creating a new instance and assigning the TwitterHandle value all in one step.

To do so, we need to create another function with the same name as our class, TwittererRedux.

class TwittererRedux
{
  # Default Constructor
  TwittererRedux ()
  {
  }

  # Constructor passing in Twitter Handle
  TwittererRedux ([string]$TwitterHandle)
  {
    $this.TwitterHandle = $TwitterHandle
  }

  # Create a property
  [string]$TwitterHandle

  # ... rest of class goes here

This technique uses overloading, as discussed in a previous post. Here we have added a single parameter, $TwitterHandle. Within the function we take the value passed in and assign it to the TwitterHandle property for the current instance, represented by $this.

Before I go on, I need to mention an important rule. When you override a constructor, you must manually add the default constructor! You can see that was done in the above sample.

So how do we use it? Pretty simple actually, when we instantiate our object by using new, we pass in the value.

# Create a new instance using an overloaded constructor
$twit = [TwittererRedux]::new('ArcaneCode')

# Display the result
$twit.TwitterHandle

Result:

ArcaneCode

Here when we called new, instead of leaving the parameter area empty we passed in a single string value. PowerShell then followed the rules of overloading as seen in the previous post. It looked over the set of constructors and found one that had a single parameter of type string and executed the code associated with it.

Let’s further expand by adding another constructor so we can assign both the handle and the name when we instantiate a new object from our class.

class TwittererRedux
{
  # Default Constructor
  TwittererRedux ()
  {
  }

  # Constructor passing in Twitter Handle
  TwittererRedux ([string]$TwitterHandle)
  {
    $this.TwitterHandle = $TwitterHandle
  }

  # Constructor passing in Twitter Handle and Name
  TwittererRedux ([string]$TwitterHandle, [string]$Name)
  {
    $this.TwitterHandle = $TwitterHandle
    $this.Name = $Name
  }

  # Create a property
  [string]$TwitterHandle

  # ... rest of class goes here

In our second constructor we have two string parameters, which will be assigned to the handle and name properties of the current object.

$twit = [TwittererRedux]::new('ArcaneCode', 'Mr. Code')
$twit.TwitterHandle
$twit.Name

Result:

ArcaneCode
Mr. Code

The Final Version

As promised, here is the final version of our TwitterRedux class.

class TwittererRedux
{
  # Default Constructor
  TwittererRedux ()
  {
  }

  # Constructor passing in Twitter Handle
  TwittererRedux ([string]$TwitterHandle)
  {
    $this.TwitterHandle = $TwitterHandle
  }

  # Constructor passing in Twitter Handle and Name
  TwittererRedux ([string]$TwitterHandle, [string]$Name)
  {
    $this.TwitterHandle = $TwitterHandle
    $this.Name = $Name
  }

  # Create a property
  [string]$TwitterHandle

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

  # Static Properties
  static [string] $Version = '2022.01.07.002'

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

  # Overloaded Function that returns a string
  [string] TwitterURL($twitterHandle)
  {
    $this.TwitterHandle = $twitterHandle
    $url = $this.TwitterURL()
    return $url
  }

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

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    # Note here we cannot call the $this.TwitterUrl function
    # because no object exists (hence no $this)
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

Constructors vs Overloading

Constructors are very similar to overloading a function, but not exactly the same.

Just like overloading, each constructor declaration must be different in terms of the number of parameters and their data types.

Unlike overloads, you have access to the properties and methods of the object. This is what let us assign values to our properties when we created the new instance of the object.

Conclusion

Constructors can aid in making our code more compact, and allowing us to assign values when we instantiate new objects. Be cautious though, it can be tempting to make far more constructors than you need. Ensure that your constructors cover only the most common situations, otherwise you’ll have a confusing mess that you have to document and maintain.

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 Classes – Overloading

Introduction

This is the next installment in our series of advanced techniques for PowerShell classes. In the previous installment we saw how to implement static properties and methods. In this one, we’ll see how to overload your methods.

We’ll take a deeper look at overloading 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 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.

Additionally, many of the code samples have lines which end in a backtick `, PowerShell’s line continuation character. 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.

In VSCode you can highlight snippet of code then press F8 to execute it. In the IDE, use F5. You can display the contents of any variable by highlighting it and using F8/F5.

Starting Point

For easy reference, here is our demo class as we left it at the end of the previous post.

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

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

  # Static Properties
  static [string] $Version = '2022.01.07.002'

  # 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()
  }

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    # Note here we cannot call the $this.TwitterUrl function
    # because no object exists (hence no $this)
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

The Need to Overload a Method

About half way into our class definition we have a method named TwitterURL. This function is pretty simple, it takes the value in the TwitterHandle property, composes the URL to the Twitter site for it, then returns it.

Here is what it would look like in action.

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

Result:

http://twitter.com/ArcaneCode

What if we had a lot of handles we wanted to get URLs for. It would be a two step process for each one, first assigning the handle to the TwitterHandle property, then calling the TwitterURL method.

$twit.TwitterHandle = 'ArcaneCode'
$twit.TwitterURL()
$twit.TwitterHandle = 'N4IXT'
$twit.TwitterURL()
$twit.TwitterHandle = 'ArcaneTC'
$twit.TwitterURL()
$twit.TwitterHandle = 'BuckWoodyMSFT'
$twit.TwitterURL()
$twit.TwitterHandle = 'tradney'
$twit.TwitterURL()
$twit.TwitterHandle = 'VKCsh'
$twit.TwitterURL()
$twit.TwitterHandle = 'TechTrainerTime'
$twit.TwitterURL()

Of course these could all be put into an array, or read in from a file and run through a foreach loop, even so it still takes two calls to our $twit object. Wouldn’t it be nice to set the TwitterHandle property and return the URL all in one method call?

But what to call the method? We could go with SetHandleAndGetURL, or perhaps UpdateAndGetTwitter, or even HeyHeresAMethodToSetTheTwitterHandleAndGetTheURL.

But in fact we already have a great name in TwitterURL. Its short and explains just what it does. It’s too bad we can’t use it more than once.

Oh wait, we can!

Implementing an Overloaded Method

To create an overload, create a new function within your class and use the same name. To differentiate, you need to have it accept a different number of parameters. Let’s make this clearer by the example below.

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

  [string] TwitterURL($twitterHandle)
  {
    $this.TwitterHandle = $twitterHandle
    $url = $this.TwitterURL()
    return $url
  }

At the top is our original function. Below it is the overloaded version. In it I pass in a single parameter, the $TwitterHandle. PowerShell can use this to determine which version of the function to call.

If you execute the TwitterURL method with no parameters, the version of the function at the top is executed.

When you call TwitterURL and pass in a parameter, the version of the function at the bottom gets run. In here I first access the TwitterHandle property of the current object (represented by $this) and update it from the parameter $twitterHandle.

Next, I called the original function to get the properly formatted URL from the (newly updated) TwitterHandle property.

I chose to do it this way to demonstrate it is possible to call the original version of a function from its overloaded version. It’s certainly not required though, as the code to format the URL could have been copied from the original function. The downside to this however is if I make a change to one area, I have to make it to both.

Also be aware that setting the TwitterHandle property may be considered a side effect by some. It’s not intuitively obvious this will happen, and some users may think this to be a bug. It’s important then to make sure you document this thoroughly in your documentation.

Let’s see it in action. First, here is the complete class with the new overloaded function added.

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

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

  # Static Properties
  static [string] $Version = '2022.01.07.002'

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

  # Overloaded Function that returns a string
  [string] TwitterURL($twitterHandle)
  {
    $this.TwitterHandle = $twitterHandle
    $url = $this.TwitterURL()
    return $url
  }

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

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    # Note here we cannot call the $this.TwitterUrl function
    # because no object exists (hence no $this)
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

After running this to get the updated class definition in memory let’s call it both ways.

# Create a new instance
$twit = [TwittererRedux]::new()

# Assign the handle, then call TwitterURL
$twit.TwitterHandle = 'ArcaneCode'
$twit.TwitterURL()

Result:

https://twitter.com/ArcaneCode

Now let’s call the overloaded version.

# Now call the overloaded version
$twit.TwitterURL('N4IXT')

Result:

https://twitter.com/N4IXT

We can also check the TwitterHandle property to ensure it has been updated.

$twit.TwitterHandle

Result:

N4IXT

We could have added additional overloads with more parameters. We could have defined [string] TwitterURL($twitterHandle, $anotherParameter), for example.

Other Ways to Differentiate an Overload

In the previous section I stated PowerShell differentiates overloads by the number of parameters passed into our function. There is one other way PowerShell can differentiate, and that is by the data type of each parameter. Let’s look at this simple example.

class over
{
  [string] hello()
    { return 'hello world' }

  [string] hello([string] $name)
    { return "hello string of $name"}

  [string] hello([int] $number)
    { return "hello integer of $number"}
}

As you can see, my class has three overloads. In the second two, we pass in a single parameter. What makes them different though is the data type for the parameter. In the first we use a string, the second an integer. To be accurate then, we need to say PowerShell can tell which overload to call by the number of parameters and the data type of each.

As should be obvious, you will need to strongly type all of your parameters for this to work, but when it comes to classes that’s not a bad idea anyway.

Just as proof, let’s see these working.

$o = [over]::new()
$o.hello()
$o.hello('mom')
$o.hello(33)

Result:

hello world
hello string of mom
hello integer of 33

You can also mix and match, with multiple data types and parameters. For example…

hello([string] $name, [int] $number)
hello([int] $number,  [string] $name)

Both of these are both valid. Just to reiterate, what you could not do is:

hello([string] $nameA, [int] $number)
hello([string] $nameB, [int] $anotherNumber)

PowerShell can’t make the distinction between the two, as they have the same number of parameters and data types in the same order.

Conclusion

Overloads can be very useful when working with classes. They allow you to continue to use method names you are familiar with yet alter them to meet your changing needs.

In our next installment we’ll cover the topic of class constructors, a way to populate properties when you instantiate your new object from the class definition.

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 Classes – Static Properties and Methods

Introduction

Over the last few articles we’ve been covering PowerShell objects. The first article in the series, Fun With PowerShell Classes – The Basics, covered the basics of using of the PowerShell class construct introduced in PowerShell version 5.

If you’ve not read it I’d suggest you do so now as we’ll be building on it in this article, as well as in the next two, as we explore the advanced capabilities of PowerShell classes. In this post we’ll cover the concept of static properties and methods.

Let me mention that for all of the examples we’ll display the code, then under it the result of our code if applicable. 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.

At the end of the line in many code samples you may notice a backtick ` character. This is PowerShell’s line continuation character. 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.

Starting Point

Just as a refresher, here is the class we originally developed.

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()
  }

}

We can create a new instance of the class by calling the static new method built into all PowerShell defined classes. Once created we can start assigning values to its properties.

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

With that reminder, let’s start diving in to some advanced features offered by classes.

Static Properties

In a previous post on creating PowerShell objects from C# code, I introduced the concept of static properties and methods. A static property or method is one that can be called without having to create a new instance of an object from the class.

To call a static method or property, use the name of the class in brackets, then two colons, then the name of the property or method you want to call. In fact, you’ve already done this in creating a new instance of a class when you used [Twitterer]::new().

It’s easy to create your own static properties and methods. Let’s create a new version of our class, and name it TwittererRedux. (Redux is a fancy word meaning ‘bring back’.) Then, we’ll add a new static property to it.

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

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

  # Static Properties
  static [string] $Version = '2022.01.07.002'

  # 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()
  }

}

In the properties area we add one new property, Version. At the front we added the keyword static. This, of course, is the indicator this property is available even without creating a new instance of the class.

Having a version number is a fairly common and useful thing to include in a class. Let’s see it in use. First though, make sure you’ve executed the above class definition for TwitterRedux to make sure it is memory.

[TwittererRedux]::Version

Result:

2022.01.07.002

Other examples of things you might wish to manifest as static properties include the author name, contact information, copyright, or perhaps a link to documentation or github where your class is stored.

Let’s turn now to the creation of a static method.

Static Methods

In our original version of the class we have a method called OpenTwitter. This accessed the objects function TwitterURL, which returned the formatted Twitter URL for the users handle, stored in the objects TwitterHandle property. Finally it opened up the Twitter page in the default browser.

It could be useful to have a function that would do something similar, only without having to go to the effort of creating a class, then populating the TwitterHandle property just so we could call this function.

We’ll do so by adding a new, static function to the class.

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

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

  # Static Properties
  static [string] $Version = '2021.01.07.002'

  # 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()
  }

  # Can launch a twitter page without instantiating the class
  static [void] OpenTwitterPage([string] $TwitterHandle)
  {
    # Note here we cannot call the $this.TwitterUrl function
    # because no object exists (hence no $this)
    $url = "http://twitter.com/$($TwitterHandle)"
    Start-Process $url
  }

}

We call the new method similar to the way we accessed our property, when we called the new method to create the class.

[TwittererRedux]::OpenTwitterPage('ArcaneCode')

If your coding went well, your default browser should open to my Twitter page (or whosever you passed in).

Restrictions on Static Properties and Methods

There is one restriction when working with static properties and methods, but it is one you need to know about.

> Static properties and methods must be self contained, and cannot reference other properties and methods of the class.

This makes sense if you think about it a moment. You are only accessing the class definition, i.e. the blue print. Normal properties and methods only exist once an object has been created from a class. While it makes sense, it isn’t intuitively obvious so I wanted to point it out.

A Note on Defining Classes

I just wanted to point out a little "gotcha" when working with classes. Within a single PowerShell script (i.e. PS1 file) you can only define a class once. Normally this is not a big issue.

However, if you are developing a class it’s possible you might want multiple versions of it. For example, at the top of the script you might want your original version.

Under it you might want basically the same code, but you’ve added a new method, or perhaps changed the code to an existing method. You want to do this for testing, so you can compare one version versus the other.

PowerShell, or more precisely VSCode or the PowerShell IDE, will generate an error for the second, third, or more versions in your code warning you it has already been defined.

The fix is pretty simple, you could just comment out all but one of the class definitions, leaving the one you are working with uncommented. Alternatively, you could just create multiple PS1 files and work with different versions in each. VSCode is especially nice for this as it lets you have your PS1 files side by side.

Conclusion

Static properties and methods are not difficult to implement, and can be quite useful. As you create your classes, think about situations where they may benefit from a static property or method.

In the next installment of this series we’ll continue our examination of the PowerShell class type by diving into overloads.

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 – Modifying Existing Objects

Introduction

So far we’ve covered a lot in this series on PowerShell Objects. We began by creating a class using the class keyword introduced in PowerShell 5. We then looked at using PSCustomObject to create new objects, then add methods to those objects. In the previous post, we used C# code to create our PowerShell objects.

In this installment, we’ll see how to add properties and methods to existing objects created by someone else. For this example we’ll use objects returned by the Get-ChildItem cmdlet, but we could use any objects.

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.

In the code samples be on the lookout for the backtick ` , PowerShell’s line continuation character, at the end of many lines. 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.

Getting The Objects to Work With

As stated in the Introduction, we will use the objects returned by the Get-ChildItem cmdlet to add a new property and method to. We’ll set our location (in my case to the folder where these samples are stored), call the Get-ChildItem cmdlet and store the result in a variable, $items.

Set-Location C:\Users\arcan\OneDrive\BlogPosts\Markdown
$items = Get-ChildItem

Let’s look a the first item in the $items collection to see what its datatype is.

$items[0].GetType()

Result:

IsPublic IsSerial Name     BaseType
-------- -------- ----     --------
True     False    FileInfo System.IO.FileSystemInfo

As you can see, each item is of type FileInfo. Each object contains information about the corresponding file it represents. You can find a full list of properties and methods for the FileInfo class in the online Microsoft Documentation for FileInfo.

Coding Our New Method

For this example, we are going to iterate over our collection of FileInfo objects. To each one, we’ll be adding one property and one method. The property will just be a number that can be used to uniquely identify each object. We’ll look more at that momentarily.

The method we’ll add will analyze the existing Extension property of the FileInfo object. As I’m sure you know, the extension is the data that occurs after the period in the file name, and is used to identify the type of file it is.

Here is the script block for this method.

# Define the custom script property
$script = {

  switch ($this.Extension)
  {
    '.cs'   {$retValue = 'C#'}
    '.md'   {$retValue = 'Markdown'}
    '.ps1'  {$retValue = 'Script'}
    '.psd1' {$retValue = 'Module Definition'}
    '.psm1' {$retValue = 'Module'}
    '.xml'  {$retValue = 'XML File'}
    '.pptx' {$retValue = 'PowerPoint'}
    '.csv'  {$retValue = 'Comma Separated Values file'}
    '.json' {$retValue = 'JavaScript Object Notation data'}
    default {$retValue = 'Sorry dude, no clue.'}
  }

  return $retValue
}

Within the switch statement, I use $this to access the current object. It then access the Extension property of the current object.

It then goes down the list, comparing the extension value to the text to the left of the squiggly brace. If it finds a match, it will run the code inside the script block. This simply sets a return value variable to a more human friendly text representation of the file type.

If no match is found, it runs the code by the default value. For more in the switch statement, see my post Fun With PowerShell Logic Branching.

Adding The Property and Method to the FileInfo Object

Now that our script is defined, it’s time to add it as well as a property to our FileInfo objects. Let’s see the code, then we’ll break it down.

# Create an item count variable
$itemCount = 0

# Iterate over each DirectoryInfo object in the $items collection
foreach($item in $items)
{
  # Add a note property, setting it to the current item counter
  $itemCount++
  $item | Add-Member –MemberType NoteProperty `
                     –Name ItemNumber `
                     –Value $itemCount

  # Add script property to the individual file object
  Add-Member -InputObject $item `
             -MemberType ScriptMethod `
             -Name 'ScriptType' `
             -Value $script

  # Now display the already existing Name property along with the
  # property and method we just added.
  "$($item.ItemNumber): $($item.Name) = $($item.ScriptType())"
}

We begin by creating a variable, $itemCount. Within the foreach loop we’ll increment it, then use it as our index for the ItemNumber property.

The foreach loop is entered, where we iterate over the collection of FileInfo objects stored in $items. Each time through the loop, the current item is copied into the $item variable. For more info on foreach, see my post Fun With PowerShell Loops.

The next line is straightforward, we simply increment the $itemCount by one.

You’ve seen the Add-Member cmdlet used in recent posts on adding properties and methods to a PSCustomObject, so I won’t delve deep into it here.

The first call to Add-Member takes the current FileInfo object, stored in $item, and adds a new property we’ll name ItemNumber. When we add it, we’ll go ahead and assign the value in $itemCount. Note that this property could be updated at a future time, although we won’t need to for this example.

We then call Add-Member a second time, adding in the script you saw earlier and naming it ScriptType.

Finally, we use string interpolation to build a nicely formatted string with the item number, the name of the file (a native property of the FileInfo object), and finally we call the method we just added ScriptType.

Here is the final output of our effort.

Result:

1: blog-template.md = Markdown
2: fun-with-powershell-classes-the-basics.md = Markdown
3: fun-with-powershell-classes-the-basics.ps1 = Script
4: fun-with-powershell-enum-flags-header.png = Sorry dude, no clue.
5: Fun-With-PowerShell-Enum-Flags.md = Markdown
6: Fun-With-PowerShell-Enums.md = Markdown
7: Fun-With-PowerShell-Objects-Part 1.md = Markdown
8: Fun-With-PowerShell-Objects-Part 1.ps1 = Script
9: Fun-With-PowerShell-Objects-Part 2.md = Markdown
10: Fun-With-PowerShell-Objects-Part 2.ps1 = Script
11: Fun-With-PowerShell-Objects-Part 3.cs = C#
12: Fun-With-PowerShell-Objects-Part 3.md = Markdown
13: Fun-With-PowerShell-Objects-Part 3.ps1 = Script
14: Fun-With-PowerShell-Objects-Part 4.md = Markdown
15: Fun-With-PowerShell-Objects-Part 4.ps1 = Script
16: fun-with-powershell-objects-part-1.png = Sorry dude, no clue.
17: Fun-With-PowerShell-Providers.md = Markdown
18: Fun-With-PowerShell-Write-Debug.md = Markdown
19: Fun-With-PowerShell-Write-Verbose-and-Write-Debug.md = Markdown
20: Fun-With-VSCode-Code-Snippets.md = Markdown
21: IMG_0965.JPG = Sorry dude, no clue.
22: more-fun-with-powershell-enums-header.png = Sorry dude, no clue.
23: More-Fun-With-PowerShell-Enums.md = Markdown
24: More-Fun-With-PowerShell-Enums.ps1 = Script
25: security-for-apartment-dwellers-01.png = Sorry dude, no clue.
26: Security-for-Apartment-Dwellers-header.png = Sorry dude, no clue.
27: Security-for-Apartment-Dwellers.md = Markdown

I author these blog posts in markdown within VSCode first, prior to copying them into my WordPress based blog. This folder contains a markdown file for each post, most of which have one or more accompanying code files associated with it.

I deliberately omitted the image type extensions (.jpg, .png) from the switch statement so you could see the default option being taken.

Persistance

There is an important fact you need to recall when using this technique. The new property and method only exist for the set of FileInfo objects contained in our $items collection. If I were to get another collection, perhaps using $moreItems = Get-ChildItem, the FileInfo objects stored in $moreItems will NOT have our ItemNumber and ScriptType in them.

You will have to explicitly add custom properties and methods to objects each time you need them.

Conclusion

As you can see, this technique offers many possibilities. You could define a script block at the top of your script that does a complex calculation, or perhaps formats data for easier reading by the end user. Then you simply add this script block to the objects you generate.

This makes your code much more readable. The complex part is at the top where we define the script block, out of the way of your loops.

It can also promote code reuse. You can create a separate script with many script blocks that you commonly use. You call that script from the one you are currently developing, and you instantly have a set of new properties and methods that can be added to the set of objects you are working with.

This method provides for extensibility with objects you did not author, or have the source code for. Perhaps you have a compiled PowerShell module that came from a vendor, but it lacks that one method that would, for your unique situation, make it much easier to work with. You can now code that method for yourself and use it.

As time goes on I’m sure you’ll find many situations you can use these techniques to solve problems.

In the next three installments of this series we’ll return to the PowerShell class type. We’ll look at some of the advanced abilities that it offers.

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 – 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!