Quick Tip on ParameterSetNames

I was writing a new function today. Oddly enough I was actually re-writing a function today and hadn’t realized it. Let me explain.

Story Time

About a half dozen times a month I find myself inspecting a remote computer and invariably the question comes up “how long has this computer been up?” I always find myself looking up how to get computer uptime in Powershell and I always look for Doctor Scripto’s blog post where he shows a one-liner that can tell you a computer’s uptime:

 
PS$> (get-date)  (gcim Win32_OperatingSystem).LastBootUpTime

The output of the command looks like this:
Uptime1

Totally sufficient. I’m usually in a remote Powershell session anyway and just copy/paste the command. I decided today that I would finally just buckle down and write a function to incorporate in my every day module that would allow me to query my own computer’s uptime as well as a remote computer. Since the info is also in the Win32_OperatingSystem class I thought I would include the date of install as this is often the “imaged” date at work which can be helpful to know as well.

Within about 10 minutes I had a rough draft of the function and it was successful in returning the information I wanted.

Uptime2

I clicked “Save As…” in VS Code and navigated to the folder where the other functions were stored only to see that there was already a function of the same name there dated just two months ago. I opened it to look at the contents and found that I had indeed written it, with some inspiration borrowed from online (and credited as such) but I didn’t actually like the way it was returning info. It also had a bit of a problem when it came to handling pipeline input. I relocated the “old” one and saved the new one in its place.

Tip of the day: ParameterSetName=”none”

The beginning of my new function was looking a lot like most of my new functions; I had declared cmdletbinding and a parameter block. Originally I had a “ComputerName” parameter to allow for specifying a computer other than the one you’re on, and then I thought to add a “Credential” parameter in case I needed to provide different credentials for the remote computer.

  
[Cmdletbinding()]
Param (
    [Parameter(Mandatory=$false,ValueFromPipeline=$true,Position=0)]
    [String]$ComputerName,
    [Parameter(Mandatory=$false,Position=1)]
    [pscredential]$Credential
)

The rest of the function was going fine but I had the thought that I wanted the function to require the “ComputerName” parameter if the Credential parameter was provided. I knew about parametersets and grouping parameters together by a name, but I wasn’t sure how this might work. I read a couple quick blog posts and saw that if I cast the “ComputerName” parameter as Mandatory and put it in the same parameterset as the “Credential” parameter it would work, but then it was ALWAYS asking for a value for the “ComputerName” parameter. In other functions where I had multiple parametersets this was handled by specfying a “DefaultParameterSetName” in the CmdletBinding definition. However, this function was only ever going to have one parameterset name. My first thought was “what if I just set it to something that doesn’t exist?”

I quickly changed the first part of my function to look like this, and it worked!

  
[Cmdletbinding(DefaultParameterSetName="none")]
Param (
    [Parameter(ParameterSetName="Remote",Mandatory=$false,ValueFromPipeline=$true,Position=0)]
    [String]$ComputerName,
    [Parameter(ParameterSetName="Remote",Mandatory=$false,Position=1)]
    [pscredential]$Credential
)

Now when calling the function with no arguments it does not ask for a “ComputerName” and returns information about the current computer. If I call the function with the “Credential” parameter but don’t supply a “ComputerName” value it will ask for one.

Uptime3

It’s a pretty unlikely scenario that I, or someone else, would call the function with JUST the “Credential” parameter and not the computer name, this was more of a proving ground type situation.

If you’d like to see the function in its entirety you can find it on my Github

That’s all for now. Until the next light bulb moment.

2024

Powershell Summit 2024

less than 1 minute read

I got the opportunity this week to attend the 2024 Powershell Summit in Bellevue Washington. If you have an opportunity to go to this, whether you’re brand ...

Back to top ↑

2023

SecretStore Module

3 minute read

SecretManagement module is a Powershell module intended to make it easier to store and retrieve secrets. The secrets are stored in SecretManagement extens...

Reset Expiration Clock

9 minute read

With more and more people working remotely there’s been a huge uptick in VPN usage. A lot of organizations have had to completely rethink some of their prev...

Status Update

1 minute read

Hi all. Just wanted to provide a brief status update. It’s been a while since my last post and while I have been busy, and making frequent use of Powershel...

Back to top ↑

2022

Get-GeoLocation

14 minute read

Getting GPS Coordinates From A Windows Machine Since 2020 a lot of organizations have ended up with a more distributed workforce than they previously had. T...

Quick Tip on ParameterSetNames

3 minute read

I was writing a new function today. Oddly enough I was actually re-writing a function today and hadn’t realized it. Let me explain. Story Time About a hal...

ProtectStrings. A Module Story

20 minute read

I’ve had an itch lately to do something with AES encryption in Powershell. I’ve tossed around the idea of building a password manager in Powershell, but I g...

Powershell all of the things. And more logging

9 minute read

“If all you have is a hammer, everything looks like a nail” - Abraham Maslow. I use a variation of this quote a lot, and I typically use it in jest, but it’s...

Back to top ↑

2021

Get-WindowsFirewallBlocks

6 minute read

Introduction I’ve had some exposure to Microsoft Defender here and there, but I was in a class with Microsoft recently where they were going over some more f...

Logging in Powershell scripts; Continued

22 minute read

In my previous post I explained a bit about some of my justifications for logging in Powershell. My interest in logging has continued since then and I spent...

Logging in Powershell scripts

7 minute read

Everyone has a different use for Powershell. Some people use it for daily administrative tasks at work. Some people are hard at work developing Powershell m...

Parsing log files with Powershell

7 minute read

Early on when I first started using Powershell I was dealing with some firewall logs from a perimeter firewall. They were exported from a SIEM in CSV format...

Get-Connections; netstat for Powershell

5 minute read

One of the tools I feel like I’ve been using for years is Netstat. It exists in both Linux and Windows (with some differences) and has similar syntax. It’s ...

Secure Credentials in Powershell

7 minute read

A coworker from a neighboring department had an interesting request one day. They wanted a scheduled task to run on a server. Through whatever mechanism the ...

Get-ADPasswordInfo

4 minute read

When I first started getting in to Powershell I was working in an IT Security position and was sifting through a lot of “noise” in the SIEM alerts. The main...

Jekyll & Minimal Mistakes; Done

less than 1 minute read

“Hello World” and all that. What started as a small conversation turned in to an Idea that I couldn’t shake: I wanted a blog. But I didn’t want a WordPress...

Back to top ↑