【问题标题】:Powershell object cannot be found with strictmode latest使用 strictmode latest 找不到 Powershell 对象
【发布时间】:2020-11-10 15:40:43
【问题描述】:

我正在尝试在set-strictmode -version latest 下工作,它在没有严格模式的情况下完全可以正常工作,不幸的是,我的环境中需要有最新的严格模式。

它的作用:通过注册表找到带有 EEELinkAdvertisement 的条目并将其分配给 $findEeeLinkAd

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

尽管在管理员中运行,但我收到一堆以下错误:

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

任何帮助将不胜感激!

【问题讨论】:

    标签: powershell android-strictmode


    【解决方案1】:

    注意

    • 除非您准备好在每次升级到新的 PowerShell 版本时彻底测试每个现有的脚本/函数/编写的 PowerShell 模块,我建议避免
      Set-StrictMode -Version Latest 在生产代码中
      - 在开发过程中很好,但是在发布代码时,应该明确指定当时的最高版本,从而锁定。如果你不这样做,现有代码在更高版本的 PowerShell 中引入新的严格性检查时可能会中断。

    • 底部显示了如何一般地处理使用有效的严格模式访问不存在的属性的尝试。

    您可以按如下方式简化您的代码,这隐含地绕过尝试访问并非在所有输入对象上都存在的属性的问题:

    $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')) { $_ } }
    

    注意从-ErrorAction SilentlyContinue-ErrorAction Ignore 的切换:后者悄悄地丢弃任何错误,而前者不显示它们,但仍然将它们记录在自动$Error 集合中。

    这利用了Microsoft.Win32.RegistryKey.GetValue() 方法悄悄地忽略 尝试检索不存在值的数据并返回$null 的事实。

    顺便说一句:将common -ErrorAction parameter 应用于Where-Object (?) 和ForEach-Object (%) cmdlet 几乎没有意义,因为参数是不是应用于传递给这些命令的脚本块 ({ ... }) 内运行的代码。


    在严格模式下访问不存在的属性时避免错误:

    Set-StrictMode-Version 2 或更高版本(包括 Latest)会导致尝试访问对象上不存在的属性以报告 statement-terminating 错误。

    • 请注意,这意味着默认情况下只有手头的语句被终止,而整个脚本执行继续

    • 还要注意-Off是默认值;也就是说,默认情况下会执行no严格性检查,这意味着即使尝试引用不存在的变量也不会默认触发错误; Set-StrictMode -Version 1 检查不存在的变量,但不检查不存在的属性

    有几种方法可以避免此类错误:

    • 在属性访问权限周围使用Try / Catch statement,同样如CFou's answer所示;这也使得在没有属性的情况下指定 默认值 变得很容易,但是与下面基于反射的方法相比,捕获异常是 缓慢

      $o = [pscustomobject] @{ foo = 1 }
      
      $propValue = try { $o.NoSuchProperty } catch { 'default value' }
      
    • 暂时子范围中禁用严格模式(这与try / catch 方法一样慢):

      $o = [pscustomobject] @{ foo = 1 }
      
      # $propValue will effectively receive $null.
      # Strictly speaking: [System.Management.Automation.Internal.AutomationNull]::Value
      $propValue = & { Set-StrictMode -Off; $o.NoSuchProperty }
      
    • 使用 reflection 测试属性的存在,通过所有对象上可用的隐藏.psobject.Properties 成员;这是最快的方法:

      $o = [pscustomobject] @{ foo = 1 }
      
      $propValue = if ($o.psobject.Properties['NoSuchProperty']) { $o.NoSuchProperty }
      

    PowerShell [Core] 7.1+ 中,您可以通过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
    
    • 自 v7.1 起的陷阱:如果您将?. 直接应用于一个变量,您必须意外地将其名称包含在{...} 中,例如${var}?.Property; $var?.Property 没有按预期工作,因为 PowerShell 然后假定变量名称为 var? - 请参阅 GitHub issue #11379 以尝试更改它。

    同样,null-coalescing operator, ??(它本身在 v7.0 中可用)可以简化提供 default 值(在早期版本中,您可以通过将 else 分支添加到 @ 987654366@以上声明):

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

    【讨论】:

      【解决方案2】:

      EeeLinkAdvertisement 是你抓取的许多物品的未定义属性,所以这是正常的。 你可以这样作弊:

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

      【讨论】:

        猜你喜欢
        • 2010-10-05
        • 1970-01-01
        • 2020-03-20
        • 2017-08-25
        • 2020-11-08
        • 2022-07-12
        • 1970-01-01
        • 2018-03-02
        • 2020-04-12
        相关资源
        最近更新 更多