The automatic variable $MyInvocation contains information about your functions such as the name, parameters, and data about how the function was called. You can use this information to debug your functions.

PowerShell is a powerful language that has inherited quite a few features of more traditional software development languages like C#. One of those is the concept of meta-programming. Loosely defined, "meta-programming" simply means that the code is aware of itself. It sounds spooky, like the code is going to become self-aware, but I assure you, the machines will not take over and you, the coder, can leverage this concept to your advantage.

PowerShell includes automatic variables. These are variables that are set by PowerShell itself and off limits to us coders. They represent various states at different times depending on the context in which the code is run. One of the automatic variables that allow your code to become self-aware is $MyInvocation. This variable contains information at any given time about how your code was invoked and is useful in some different situations.

First of all, why would you need to write code that is aware of itself anyway? Let's start off with a simple example. Let's say you have a bunch of functions that call one another. The script that kicks off all of these functions is hundreds of lines long. You're finding that your script is failing in various places in seemingly random functions, and you can't figure out why. You decide to add some verbose messaging to the console when the script runs. You'd like to see when your script enters and exits each of your functions. You begin by doing something like this:

Function MyFunction1 {
     [CmdletBinding()]
     param()
     Write-Verbose 'Entering function MyFunction1...'
     ## Do some stuff here
     Write-Verbose 'Exiting function MyFunction1...'
 }

Note: The $VerbosePreference variable determines whether verbose messages are displayed. For instance, if you enter $VerbosePreference = 'Continue' on your console Write-Verbose will display the verbose messages if you execute the function.

After spending forever doing this for dozens of your functions, it works but then you need to change your function names. This requires you to not only modify the function names but also the verbose messaging as well. This is not manageable in the long run. There's got to be a better way. You need your verbose messaging to just know what function it's in. That way, you can just reuse the same line over and over without having to worry about the function name changing.

Luckily for us, we have the $MyInvocation variable. This variable contains lots of different state environment information about the script, function, etc., that it's currently in. In the above example, let's put the $MyInvocation variable inside of the MyFunction1 function and call it to see what happens.

Function MyFunction1 {
     [CmdletBinding()]
     param()
     Write-Verbose 'Entering function MyFunction1...'
     ## Do some stuff here
     Write-Verbose 'Exiting function MyFunction1...'
     $MyInvocation
 }
Looking at the $MyInvocation variable

Looking at the $MyInvocation variable

In this example, I simply copied and pasted the function directly into my console. Now, I'll put the function into a script, execute the function inside of the script, and run the script.

Looking at $MyInvocation in a script

Looking at $MyInvocation in a script

Notice how you now get the script path from which the function was called. $MyInvocation knows various states regarding the function it was called within.

What does this have to do with our example above? Recall that we needed to statically add the function name to each verbose message. With the information that $MyInvocation provides, we don't have to do this anymore. We simply need to use a property of $MyInvocation and reference that instead. To get the function name, we need to use $MyInvocation.MyCommand. I'll go ahead and place this in my function.

Function MyFunction1 {
     [CmdletBinding()]
     param()
     Write-Verbose 'Entering function MyFunction1...'
     ## Do some stuff here
     $MyInvocation.MyCommand
     Write-Verbose 'Exiting function MyFunction1...'
 }

I get an output like in the screenshot below.

Using the Name property on $MyInvocation

Using the Name property on $MyInvocation

However, we only need the function name, so I'll use the Name property as $MyInvocation.MyCommand.Name. If I execute the function now, I will just get the name. Great! Now all I have to do is put this in my verbose message, and we're done!

Function MyFunction1 {
     [CmdletBinding()]
     param()
     Write-Verbose "Entering function $($MyInvocation.MyCommand.Name)…"
     ## Do some stuff here
     Write-Verbose "Exiting function $($MyInvocation.MyCommand.Name)…"
 }

You can now see that the function name is a variable. It will represent the name of whatever function that $MyInvocation is currently in.

Subscribe to 4sysops newsletter!

$MyInvocation in a function

$MyInvocation in a function

As you can see, $MyInvocation contains a lot of useful information. Use this variable any time you need to discover how a function or even a script was executed. The $MyInvocation variable has numerous properties. I suggest looking through these properties and exploring new ways to use it. You'll find that you'll come up with all kinds of interesting use cases.

1 Comment
  1. Mike Ciokiewicz 7 years ago

    Thank you very much for the tutorial, it’s very helpful to gain insight to the many offerings of Powershell and how they can help in everyday scenarios.  I (we all) appreciate the authors of this blog and how you give an idea, and example of the idea and then explain in depth of how and why it works.

    Thanks again, Mike

Leave a reply

Your email address will not be published.

*

© 4sysops 2006 - 2023

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account