powershellandroid-strictmode

Powershell object cannot be found with strictmode latest


I am trying to get below to work under set-strictmode -version latest, it works completely fine without strict mode, unfortunately it's a requirement to have latest strictmode in my environment.

What it does: go through registry to find the entry with EEELinkAdvertisement and assign it to $findEeeLinkAd

$findEeeLinkAd = Get-ChildItem -LiteralPath 'hklm:\SYSTEM\ControlSet001\Control\Class' -Recurse -ErrorAction SilentlyContinue | `
   % {Get-ItemProperty -Path $_.pspath -ErrorAction SilentlyContinue | `
  ? {$_.EeeLinkAdvertisement} -ErrorAction SilentlyContinue }

I receive a bunch of the following errors despite running in Administrator:

The property 'EEELinkAdvertisement' cannot be found on this object. Verify that the property exists.
At line:3 char:12
+         ? {$_.EEELinkAdvertisement} }
+            ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], PropertyNotFoundException
    + FullyQualifiedErrorId : PropertyNotFoundStrict

Any help would be appreciated!


Solution

  • Note:

    You can streamline your code as follows, which implicitly bypasses the problem of trying to access a property not present on all input objects:

    $rootKey = 'hklm:\SYSTEM\ControlSet001\Control\Class'
    
    # Find all keys that have a 'EeeLinkAdvertisement' value.
    $findEeeLinkAd = 
      Get-ChildItem -LiteralPath $rootKey -Recurse -ErrorAction Ignore | 
        ForEach-Object { if ($null -ne $_.GetValue('EeeLinkAdvertisement')) { $_ } }
    

    Note the switch from -ErrorAction SilentlyContinue to -ErrorAction Ignore: the latter quietly discards any errors, whereas the former doesn't display them, but still records them in the automatic $Error variable, which is a session-wide collection of all (non-ignored) errors.

    This takes advantage of the fact that the Microsoft.Win32.RegistryKey.GetValue() method quietly ignores attempts to retrieve data for a nonexistent value and returns $null.

    As an aside: It is virtually pointless to apply the common -ErrorAction parameter to the Where-Object (?) and ForEach-Object (%) cmdlets, because the parameter is not applied to the code that runs inside the script blocks ({ ... }) passed to these commands.


    Avoiding errors when accessing non-existent properties in strict mode:

    Set-StrictMode with -Version 2 or higher (including Latest) causes attempts to access a nonexistent property on an object to report a statement-terminating error.

    There are several ways of avoiding such errors:

    In PowerShell [Core] 7.1+, you can do this more succinctly, via the null-conditional operator ?.:

    $o = [pscustomobject] @{ foo = 1 }
    
    # Note the `?.`, which only tries to access the property if the expression
    # to the left isn't $null.
    $propValue = $o.psobject.Properties['NoSuchProperty']?.Value
    

    Similarly, the null-coalescing operator, ?? (which itself became available in v7.0) can simplify providing a default value (which in earlier versions you can achieve by adding an else branch to the if statement above):

    $o = [pscustomobject] @{ foo = 1 }
    
    # The RHS of `??` is used if the LHS evaluates to $null.
    $propValue = $o.psobject.Properties['NoSuchProperty']?.Value ?? 'default value'