Unexpected String Inequality Using Variable "$MyInvocation" Directly

This topic contains 2 replies, has 2 voices, and was last updated by Profile photo of Zoggerine Zoggerine 8 months, 1 week ago.

Viewing 3 posts - 1 through 3 (of 3 total)
  • Author
    Posts
  • #34084
    Profile photo of Zoggerine
    Zoggerine
    Participant

    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.

    #34087
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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.

    #34088
    Profile photo of Zoggerine
    Zoggerine
    Participant

    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.

Viewing 3 posts - 1 through 3 (of 3 total)

You must be logged in to reply to this topic.