Unraveling the Mystery of $MyInvocation

PowerShell graphic

You have seen $MyInvocation before. It was probably in a piece of code online or on GitHub. Perhaps, you observed it used in a module you downloaded from the PowerShell Gallery or came across it in a PowerShell book you are reading. And like me, you have probably wondered to yourself what its use was. When I would see it, my brain always registered it as noise that was not essential to the functionality of the code. I thought it was used for verbose logging and other informational recordings. However, I have seen it in enough code to make me want to understand what it is and why to use it. Let’s investigate more.

 

 

Starting Simple with Get-Help

My research began with a simple get-help command. This is the place you always start to investigate things in PowerShell. Not really knowing what to search on exactly, I started out here:

MyInvocation1

Once I found the about_Automatic_Variables topic, I was hopeful I would find more and I did. The $MyInvocation automatic variable provides information about the current command, including name, parameters, and information about how the command was invoked. Further, it notes that $MyInvocation only gets populated for scripts, functions, and script blocks. That was enough information to get me started.

Retrieving Properties with Get-Member

Next, I used the get-member command to retrieve the properties of $MyInvocation. I wanted to see what kind of useful information it contained.

$MyInvocation | Get-Member

$MyInvocation contains about 15 different properties. I tried displaying the contents of the automatic variable and was disappointed. It tells me the command that ran and a couple of other properties. It told me the HistoryID, which is the command number in my get-history list. It also told me a couple of other properties but I am not quite sure of the importance.

MyInvocation2
Next, I recalled from the help that this variable only gets populated for scripts, functions, and script blocks. This means that trying to display it in the console would not give me useful information.

Investigating $MyInvocation in a Script

I then wrote a simple script and saved it as a file names script.ps1. I ran the script from inside the ISE using the green Play button and I got one additional property populated, InvocationName. This tells me the name of the script, which is interesting. I still wanted more!

$MyInvocation | format-list

MyInvocation3

Next, I tried running the same script from the console window and I got the Line and Position Message properties populated. Neither of these came with any useful information.

MyInvocation4

With that output being underwhelming, I decided to check it out within a function instead.

Getting Invocation Information Out of Your Functions

Next, I took that same one-line script, enclosed it in a function Get-MyInvocation {} declaration, and saved it as Get-MyInvocation.ps1. I loaded it into memory using the ISE and called it from the console. This is the same thing I did in the script example but I received the same result I received when I ran the script. For the next test, I placed the call to the function directly in the file with the function and saved that as Get-MyInvocationScript.ps1.

function get-MyInvocation {
   $MyInvocation | format-list
   }
get-MyInvocation

MyInvocation5

We are starting to get somewhere! Notice the information that is available on $MyInvocation within the function. It tells me script name (C:\temp\get-myinvocationScript.ps1), which is the name of the script that I ran. I also get information about the line of the script. Granted, there is only one line in the script, which is the one that calls the function on line 7. Additionally, it tells me the script root directory in PSScriptRoot and the path to the script in PSCommandPath.

What Can I Do with $MyInvocation?

Earlier in the article, I mentioned using $MyInvocation for verbose logging, almost with an air of disdain. However, this is one of the really cool uses of the properties of $MyInvocation because you understand where the information comes from. Perhaps, you have a script that calls multiple functions. Within the functions, you include verbose logging that tells you exactly what function the information is coming from by using $MyInvocation.MyCommand. This makes debugging much more simple. On the other hand, you may have a script that calls a function multiple times with different parameters. You could use the $MyInvocation.ScriptLineNumber property to figure out which function call brought in the problem. But speaking of parameters…

Reporting Parameter Information with $MyInvocation

Let’s now add a parameter to the get-MyInvocation function. I added a string parameter named $MyInfo to the function and write-host will display it to the console.

function get-MyInvocation {
   param (
   [string]$MyInfo
   )

   Write-Host 'The input parameter $MyInfo is'"$($MyInfo)"
   $MyInvocation | format-list
   }

Next, I change the get-myInvocationScript script to use some parameters. In this example, I am using the -MyInfo parameter as well as an undeclared parameter, -AnotherArg.

. .\get-MyInvocation.ps1
get-MyInvocation -MyInfo "WOW!!!" -AnotherArg "OMG"

When I run get-MyInvocationScript, I get information about both parameters that were passed from the calling script. The MyInfo parameter and the value “WOW!” are now listed in the BoundParameters section. The AnotherArg parameter and the value “OMG” show up in the UnboundArguments list. I can see exactly what was passed into the function this way. Think back to the earlier example where a function call occurred multiple times with different parameters in the same script. In that example, using the information from $MyInvocation can really help narrow down the problem areas in a script.

MyInvocation6

$MyInvocation Mystery Solved!

After learning more about it, I now see the usefulness of using $MyInvocation. Yes, it still holds true that the meat of the code does not require its use. To continue with the food analogy, I mentally compared $MyInvocation to a garnish. It is pretty but not very useful. After exploring it some more, I find it is more like a vegetable. Vegetables are side dishes that can add nutrients to your body and easier debugging keeps your code healthy. In complicated code, such as recursive functions, $MyInvocation becomes a handy informational tool for your PowerShell toolbox.