Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Building More PowerShell Functions

Posted on January 3, 2019January 3, 2019

In a recent post I discussed the the process you might go through in developing a PowerShell function. By the end, I not only had a new tool for my PowerShell toolbox, but I had a function outline that I could re-use. If you read the previous article then you should recognize the idea of "managing at scale". Where possible I want my functions to work for not one thing or computer for many. One way to accomplish that is by incorporating remoting. The process memory tool I built leveraged Invoke-Command to run a simple PowerShell expression using Get-Process to retrieve the information I wanted. I can re-use that technique to accomplish all sorts of tasks. Let's do another.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

Start with a Command

Whenever you are building a PowerShell script or function, I stress that you should begin with a command or set of commands that you can run from the console. This will be the core of the script or function. A lot of your scripting is adding convenience, error handling and other embellishments around this core. For my next function I wanted to replicate the information displayed when you run the winver.exe command. To see for yourself run winver at a prompt or in the Run box.

Much of the information displayed can be retrieved by querying the Win32_OperatingSystem class using Get-CimInstance.  I consider Get-WmiObject deprecated and rarely use it now. However, I also know that the same information can be found in the registry. So for a change of pace I decided to query the registry to get the same information and ended up with this code.

$RegPath = 'HKLM:\SOFTWARE\Microsoft\Windows nt\CurrentVersion\'

Get-ItemProperty -Path $RegPath | Select-Object -Property ProductName, EditionID, ReleaseID,
@{Name = "Build"; Expression = {"$($_.CurrentBuild).$($_.UBR)"}},
@{Name = "InstalledUTC"; Expression = { ([datetime]"1/1/1601").AddTicks($_.InstallTime) }},
@{Name = "Computername"; Expression = {$env:computername}}

I am always thinking about writing an object to the pipeline so I'm defining some custom properties that not only replicate what I see in winver but that might also be useful.

Getting Windows version from the registry with PowerShell

Now that I have code that works,  I can plug this code into the scriptblock for my function. Actually, let me take a step back first.

Using a Function Template

The Get-ProcessMemory function I wrote in the end became a terrific model I could re-use. So I created a template version of the file. You can get the template from GitHub.

I even added comment based help for all of the remoting parameters. In the Begin block there is a section to define the scriptblock that I intend to run remoting. That is where I'll stick my registry-related code.  I don't need to pass any other parameters. If I did I would add them and update the help. The important steps include updating the scriptblock to incorporate those values either by employing the $using: reference or passing an ArgumentList parameter to Invoke-Command. My template is splatting PSBoundParameters to Invoke-Command so I (or you) need to add or remove parameters accordingly.

When finished, I had a new command called Get-WindowsVersion.

A PowerShell Windows Version Tool

Now I have a scalable PowerShell tool!

Extending the Function

Even though I'm always stressing the importance of "objects in the PowerShell pipeline", I recognize that sometimes we really need a string or piece of text. When running winver.exe that is essentially what I'm seeing. Obviously the graphical tool doesn't scale. But PowerShell can. I already have all the pieces of information in the output from my function to create the string. My initial thought was to add a parameter to the function, like -AsString, that if used, would write a string to the pipeline instead of the object. That would be the lazy way and I realize the wrong way.

PowerShell functions should only write one type of object to the pipeline and I was potentially creating a function what was going to do 2 things. The answer, naturally, was to write a second function, Get-WindowsVersionString. This would actually be easy to write because all I need to do is call my Get-WindowsVersion function for each computer and create the string from the result. This becomes the Process scriptblock.

Process {

    $results = Get-WindowsVersion @PSBoundParameters

    #write a version string for each computer
`   foreach ($result in $results) {
        "{0} Version {1} (OS Build {2})" -f $result.ProductName, $result.releaseID, $result.build
    }

} #process

The parameters for this function are the same as Get-WindowsVersion so all I have to do is "pass" them using splatting. You can see the flow in the functions' verbose output.

Getting a Windows Version String with PowerShell

The end result is I have 2 functions to easily get me the information I need and in different formats. The code for both functions is also on Github.

VS Code Bonus

If you scroll down the code for my Get-Something template you'll see a comment block at the end of the file. This is a json code snippet. You copy and paste this into the PowerShell snippets json file for VSCode.  If you don't know how to get there, click on the gear icon and select User Snippets. Select the powershell.json file. Paste the snippet into this file. Watch your commas!

With this snippet in place I can quickly build a new function by starting to type 'get-something'.

Using the Get-Something Snippet in VSCode

Press Enter to insert the snippet. Add your scriptblock (which you already know works, right?), adjust parameters, update help and you're done!

A Process Paradigm

I hope you have found these last few articles helpful in building your own PowerShell scripts and functions. My end results aren't the goal and actually aren't that relevant. The main thing you should be focusing on is a process and pattern in PowerShell toolmaking. If you can "template-tize" it, so much the better. Your feedback is always welcome. I'm very interested in what roadblocks you face or what you find difficult to understand. You might also be interested the PowerShell Scripting and Toolmaking Book in learning more scripting paradigms and concepts.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

2 thoughts on “Building More PowerShell Functions”

  1. Joshua Badman says:
    January 3, 2019 at 10:13 pm

    Typo in line 243 , ? Watch your commas!

    1. Jeffery Hicks says:
      January 4, 2019 at 8:34 am

      I guess I caught it in my local copy after I created the gist. I moved the functions to my PSScriptTools module and they look right.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d