Archives
- April 2018
- March 2018
- August 2017
- June 2017
- May 2017
- April 2017
- March 2017
- February 2017
- January 2017
- December 2016
- November 2016
- October 2016
- September 2016
- June 2016
- May 2016
- August 2015
- June 2015
- February 2015
- November 2014
- September 2014
- April 2014
- February 2014
- December 2013
- September 2013
- June 2013
- April 2013
- November 2012
- August 2012
- July 2012
- April 2012
- March 2012
- January 2012
- November 2011
- October 2011
- August 2011
- April 2011
- March 2011
- February 2011
- December 2010
Categories
- $Profile
- Active Directory
- Annoyances
- Application Compatibility
- Authentication
- Building Labs
- Console
- DHCP
- Essentials
- Exchange
- Group Policy
- Hardware
- Hyper-V
- IT Admin
- Kindle
- MultiPoint
- net commands
- Network Administration
- Networking
- Patching
- PowerShell
- PowerShell Functions
- PSCredential
- RD Session Host
- RDSH
- Registry
- Remote Desktop
- RemoteApp
- RemoteFX
- SBS
- Security
- Survival Guide
- Uncategorized
- Windows 10
- Windows Azure
- Windows Backup
- Windows Server
- Windows Server 2016
- Windows Server Core
- Windows Update
- WMF
- WMI
- WMS
To find out more, including how to control cookies, see here: Cookie Policy
Param() Tricks

One of the new features of PowerShell v5 is support for creating hard links, symbolic links and junctions. This is long overdue, and much appreciated. Before, I'd been forced to the workaround of using "cmd /c mklink" to create links, and I'm always glad to find a way to get rid of any vestige of cmd. Plus, having it as a part of PowerShell gives me way more flexibility in creating scripts.
As I was looking at some of my existing scripts, it occurred to me that I should be taking advantage of hard links in more scripts. I already use hard links for my various RDP connects, using a long switch statement. (I'll write that up one of these days, it's actually pretty cool.) But what caught my eye today was the script I wrote to create virtual machines for my labs -- New-myVM.ps1. I have a -Client parameter to the script that is a Boolean, defaulted to $False:
[CmdletBinding()] Param([Parameter(Mandatory = $True,Position = 0)] [alias("Name")] [string] $VmName, [Parameter(Mandatory=$False)] [Boolean] $Client=$False )
Which is OK, but it occurred to me that I could do better. So, first, I created a new, hard-linked file with:
New-Item -Type HardLink -Name New-myClientVM.ps1 -Path .\New-myVM.ps1
Now I have one file with two names. Cool. So, let's take that a step further. I can tell which version of it I called from the command line by taking advantage of the automatic PowerShell variable $myInvocation:
$myInvocation.mycommand.name
This returns the filename (".name") of the command (".mycommand") that was executed ($myInvocation). So now, I can use:
$client = ($myInvocation.mycommand.name -match "client")
I put that near the top of the script, and now I could branch depending on whether I was creating a server VM or a client VM. Which was definitely better, but still left me thinking it could be improved.
So, how about making the whole thing a lot cleaner by getting rid of that extra line? After all, I'm creating a variable and defaulting its value to $false, but why not default its value more intelligently, controlled by which file I executed to create the VM? I can still override it with the parameter (so no scripts that call this script will break), but now, I can set it automatically without using a parameter at all.
[CmdletBinding()] Param([Parameter(Mandatory = $True,Position = 0)] [alias("Name")] [string] $VmName, [Parameter(Mandatory=$False)] [Boolean] $Client=($myInvocation.myCommand.Name -match "Client") )
Now that pleases me. It feels "cleaner", it's clear what I'm doing, and it doesn't take any longer to evaluate than it would as a standalone line.
Leave a Reply