Unexpected String Inequality Using Variable "$MyInvocation" Directly

Hi all,

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.

$scr = $($MyInvocation.MyCommand.Path)
$scr -eq $($MyInvocation.MyCommand.Path)

''
gci | ?{
	!($_.FullName -eq $scr)
}

''
gci | ?{
	!($_.FullName -eq $($MyInvocation.MyCommand.Path))
}

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.

PS C:\Users\Me\Desktop\New folder> test.ps1
True



    Directory: C:\Users\Me\Desktop\New folder


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        20/01/2016   6:38 PM          0 file.txt

-a---        20/01/2016   6:38 PM          0 file.txt
-a---        20/01/2016   8:55 PM        249 test.ps1


PS C:\Users\Me\Desktop\New folder>

If both variables “$scr” and “$($MyInvocation.MyCommand.Path)” are the same, then why aren’t the outputs the same? Have I overlooked something?

I’m using PowerShell 4.0 and I cannot observe this erroneous result in PowerShell 2.0, leaving me to believe that this is an introduced bug.

Can somebody confirm this?

Thanks in advance.

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.

Thank you very much for your response, Dave.

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.

E.g., take for instance this script,

"`nGci:"
dir

"`nWhere:"
gci | ?{
	!($_.FullName -eq $($MyInvocation.MyCommand.Path))
}

"`nForeach:"
gci | %{
	!($_.FullName -eq $($MyInvocation.MyCommand.Path))
}

Then observe it’s output in Posh 4 then 2.

PS C:\Users\Me\Desktop\New folder> test.ps1

Gci:


    Directory: C:\Users\Me\Desktop\New folder


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        20/01/2016   6:38 PM          0 file.txt
-a---        21/01/2016   1:35 AM        217 test.ps1

Where:
-a---        20/01/2016   6:38 PM          0 file.txt
-a---        21/01/2016   1:35 AM        217 test.ps1

Foreach:
True
False


PS C:\Users\Me\Desktop\New folder> powershell -ver 2 -nolo
PS C:\Users\Me\Desktop\New folder> test.ps1

Gci:


    Directory: C:\Users\Me\Desktop\New folder


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        20/01/2016   6:38 PM          0 file.txt
-a---        21/01/2016   1:35 AM        217 test.ps1

Where:
-a---        20/01/2016   6:38 PM          0 file.txt

Foreach:
True
False


PS C:\Users\Me\Desktop\New folder>

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.

Thank you again, Dave.