So I was doing something simple, I was attempting to list the contents of the current directory without listing the script file itself. I know I could have simply have done
gci -Exclude $($MyInvocation.MyCommand.Name)
But I chose to do it using pipes to Where-Object. And I wasn’t impressed with the outcome… Firstly, here’s some script.
The two Get-ChildItem commands are similar in almost every way, the only difference being the variable names used for the string comparison. They should be perfectly equivalent, as can be observed, because one of the variables, “$($MyInvocation.MyCommand.Path)”, is assigned directly to the other variable, “$scr”. Performing a comparison test for equivalence, the -Eq operator says that “$scr” and “$($MyInvocation.MyCommand.Path)” are indeed the same, however, results from Get-ChildItem tell a slightly different story.
Here is sample output for the above mentioned script.
The $MyInvocation automatic variable changes contents constantly, every time you call a cmdlet or function. That’s why your code to assign contents of that object to a variable works the way you’d expect, but the second bit of code doesn’t.
Your post explains a lot to me. I was heavily under the impression that the contents of the automatic variable $MyInvocation was constant thought the runtime of the script.
For getting the name of the current running cmdlet or function, I had always just used advanced functions and accessed $PSCmdlet.MyInvocation, never considering if $MyInvocation actually worked in user-defined cmdlets/functions.
I figured out why the output of the script differs in PowerShell 2.0 and 4.0…
It appears, under PowerShell 4.0, in a Where-Object construct, the object $MyInvocation.MyCommand does not exist. However, in PowerShell 2.0, $MyInvocation.MyCommand is populated with information about the script context, which is the same behaviour in Foreach-Object for both versions.
I don’t like the output I get from PowerShell 4.0. It doesn’t seem intuitive to have $MyInvocation.MyCommand work a certain way in Foreach-Object and then just not work in the Where-Object cmdlet. But at least it’s good to know about this difference.