question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

$MyInvocation.MyCommand.Name becomes null in Where-Object block

See original GitHub issue

Issue description: Unable to use $MyInvocation.MyCommand.Name in Where-Object block as it becomes null. ForEach and For-EachObject works fine. I see this only with Where-Object.

I understand there are workarounds but just want to know if this is expected behavior or not as I was not able to find document that describes scope in Where-Object.

Steps to reproduce

Copy the following script to test.ps1

1 | Where-Object{
    Write-Host('MyInvocation in Where-Object: ' + $MyInvocation.MyCommand.Name)
}

1 | ForEach-Object{
    Write-Host('MyInvocation in ForEach-Object: ' + $MyInvocation.MyCommand.Name)
}

ForEach($FileName in 1){
    Write-Host('MyInvocation in ForEach: ' + $MyInvocation.MyCommand.Name)
}

Then run

.\test.ps1

Expected behavior

## Expected output in case script name is test.ps1.

MyInvocation in Where-Object: test.ps1
MyInvocation in ForEach-Object: test.ps1
MyInvocation in ForEach: test.ps1

Actual behavior

## Expected output in case script name is test.ps1.

MyInvocation in Where-Object:       <-------- $MyInvocation.MyCommand.Name becomes null 
MyInvocation in ForEach-Object: test.ps1
MyInvocation in ForEach: test.ps1


Environment data

> $PSVersionTable

Name Value
---- -----
PSVersion 6.2.1
PSEdition Core
GitCommitId 6.2.1
OS Microsoft Windows 10.0.18362
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0

Issue Analytics

  • State:open
  • Created 4 years ago
  • Comments:16 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
daxian-dbwcommented, Sep 4, 2019

I agree. We need to decide which behavior is the correct one. From my personal view, Where-Object seems doing the right thing because just like @BrucePay said, a script block is an anonymous function.

Here is another example:

PS> cat .\b.ps1
. { Write-Host('MyInvocation in the script block: ' + $MyInvocation.MyCommand.Name) }
PS> .\b.ps1
MyInvocation in the script block:

Here, b.ps1 contains an invocation of a script block, and as we can see, the script block doesn’t uses b.ps1 as the command name.

#10454 is related to this issue. The PR made an optimization to override ForEahc-Object with dot-sourcing a filter-like script block for some common uses of ForEach-Object, and when that optimization kicks in, $MyInvocation.MyCommand.Name is null for ForEach-Object too. Whether that should be fixed and how to fix it depends on the conclusion of this issue.


Here are the output of $MyInvocation from Where-Object and ForEach-Object in the repro scenario as in preview.3:

MyInvocation in ForEach-Object:

MyCommand             : a.ps1
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 1
OffsetInLine          : 1
HistoryId             : 46
ScriptName            :
Line                  : .\a.ps1
PositionMessage       : At line:1 char:1
                        + .\a.ps1
                        + ~~~~~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        : .\a.ps1
PipelineLength        : 1
PipelinePosition      : 1
ExpectingInput        : False
CommandOrigin         : Runspace
DisplayScriptPosition :
MyInvocation in Where-Object:

MyCommand             :
BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 1
OffsetInLine          : 1
HistoryId             : 47
ScriptName            :
Line                  : .\c.ps1
PositionMessage       : At line:1 char:1
                        + .\c.ps1
                        + ~~~~~~~
PSScriptRoot          :
PSCommandPath         :
InvocationName        :
PipelineLength        : 0
PipelinePosition      : 0
ExpectingInput        : False
CommandOrigin         : Internal
DisplayScriptPosition :

Here is the output of $MyInvocation from ForEach-Object in the repro scenario with the optimization change in #10454:

MyInvocation in ForEach-Object:

MyCommand             :
                            'MyInvocation in ForEach-Object: '
                            $MyInvocation | fl *

BoundParameters       : {}
UnboundArguments      : {}
ScriptLineNumber      : 5
OffsetInLine          : 36
HistoryId             : 32
ScriptName            : F:\tmp\a.ps1
Line                  : 1..2 | Where-Object { $_ -gt 1 } | ForEach-Object {

PositionMessage       : At F:\tmp\a.ps1:5 char:36
                        + 1..2 | Where-Object { $_ -gt 1 } | ForEach-Object {
                        +                                    ~~~~~~~~~~~~~~~~
PSScriptRoot          : F:\tmp
PSCommandPath         : F:\tmp\a.ps1
InvocationName        : ForEach-Object
PipelineLength        : 2
PipelinePosition      : 2
ExpectingInput        : True
CommandOrigin         : Internal
DisplayScriptPosition :
1reaction
SteveL-MSFTcommented, Dec 18, 2019

@PowerShell/powershell-committee reviewed this. Inspecting the code, it appears that both Where-Object and ForEach-Object both have code to set MyInvocation, but using different APIs. It seems that user found utility in getting this information so we recommend that Where-Object should behave like ForEach-Object even if it is technically correct that it’s an anonymous function.

Read more comments on GitHub >

github_iconTop Results From Across the Web

$MyInvocation.MyCommand.Path returning NULL
$MyInvocation.MyCommand.Path will only return path if called from the $script: scope . See $MyInvocation.MyCommand.Path is $null in PowerGUI ...
Read more >
$MyInvocation.MyCommand object is set to null when you ...
$MyInvocation.MyCommand object is set to null when you run the script by using PowerShell 3.0 in Windows 8 or in Windows Server 2012....
Read more >
param block breaks script?? Weird behavior, probably ...
I'm still trying to automate some of the things I "just do" at the command line in PS. Specifically, the complaint comes in:...
Read more >
Public/Update-OSMedia.ps1 21.10.13.1
if ($MyInvocation.MyCommand.Name -eq 'New-OSBuild') { if ($PSCmdlet.ParameterSetName -eq 'Taskless') { #$Task = Get-OSMedia -Revision OK | Where-Object {$_.
Read more >
PowerShell: The automatic variable $MyInvocation
The automatic variable $myInvocation stores information about the current command if the command is a function, a script or a script block.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found