In normal mode, accessing a property that does not exist returns $null. StrictMode disables this and makes it an exception. That is consistent over several commands - except Get-Member which returns $null. This is surprising, and I expected it should also raise an exception. Should it?
Test cases:
PS C:\> Set-StrictMode -Version 2
PS C:\> $x = Get-Item 'C:\windows'
PS C:\> $x.pretend
The property 'pretend' cannot be found on this object. # PropertyNotFoundStrict
PS C:\> $x | Select-Object -ExpandProperty pretend
Select-Object : Property "pretend" cannot be found # ExpandPropertyNotFound
PS C:\> $x | ForEach-Object -MemberName pretend
ForEach-Object : The input name "pretend" cannot be resolved to a member. # PropertyOrMethodNotFound
PS C:\> $x | Where-Object -Property pretend -eq $null
Where-Object : The input name "pretend" cannot be resolved to a property. # PropertyNotFound
PS C:\> $x.foreach('pretend')
The property 'pretend' cannot be found on this object. # PropertyNotFoundStrict
PS C:\> $x | Get-Member -Name pretend # outputs $null
I'm half-thinking it's best to leave it so that we have _some_ way of figuring out whether a property exists or not without throwing an exception.
🤷♂️
I see your point, @vexx32. Using an expression you could do [bool] $x.psobject.properties['pretend'] or [bool] $x.psobject.methods['pretendMethod'], however.
@HumanEquivalentUnit, note that Select-Object -ExpandProperty pretend _always_ reports a _non-terminating_ error (per input object that lacks the property), irrespective of the strict-mode setting (strict-mode violations are _statement-terminating_ errors).
I doubt it would be possible to change now without breaking existing code; perhaps only document it. But my question is, was that deliberate or accidental?
@mklement0 you might have seen the related discussion #9086 including testing whether properties exist before using them, in strictmode. I didn't note that Select-Object -ExpandProperty always reports errors for absent properties, that is interesting. I did note that Select-Object -Property Nme with a typo, works perfectly fine in strictmode, no errors about absent properties, and does make an object with a property Nme = $null, just as it would in normal mode.
As per the null-soaking issue, if the intent of StrictMode PropertyNotFound exceptions is to guard against typos, avoid propagating $null, or assert the object is the type you expected it to be, this behaviour of Get-Member and normal behaviour of Select-Object -Property, don't seem consistent with it.
I see your point re Select-Object -Property, @HumanEquivalentUnit.
The tension is between:
wanting to ensure in strict mode that you've only specified a _preexisting_ property
the convenience of intentionally _creating_ a property / ensuring its existence across heterogenous input.
Both use cases are valid.
Similarly, with Get-Member, you could argue that Getting something with an (umambiguous, non-wildcard) name that doesn't refer to something existing should fail in strict mode.
It relates to the discussion about having separate Test-* cmdlets if the intent is merely to _test_ existence - see https://github.com/PowerShell/PowerShell/issues/7498#issuecomment-414350751
I'm not sure what the right answer is, but I agree that at least updating the docs is called for.
I stumbled upon this with regard to select-object.
Set-StrictMode -Version latest
$PSVersionTable | select-object `
@{ Name = "Dummy"; Expression = { $_.DoesNotExist } }
I would expect this to fail, or at least have a possibility to make it fail.
@leonardder
Problem with that is that
$PSVersionTable | Select-Object @{ n='Dummy'; e={ throw }}
also fails silently
You're correct. Slightly worrying.
Yeah slightly, but that's also how properties tend to work in PS (and you could consider that expression to be somewhat of a property get accessor). e.g.
public class MyObject
{
public string MyProperty => throw new System.InvalidOperationException();
}
Accessing MyProperty on that object will work mostly the same.
That's good to know, @SeeminglyScience, but perhaps even more worrying (I know that this ship sailed a long time ago), given that _setting_ properties and _method calls_ do surface exceptions.
As it stands, it is impossible to surface errors from the script blocks of calculated properties.