Jef*_*eff 4 powershell android-strictmode
我正在尝试在下面工作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 }
Run Code Online (Sandbox Code Playgroud)
尽管在管理员中运行,我还是收到了一堆以下错误:
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
Run Code Online (Sandbox Code Playgroud)
任何帮助,将不胜感激!
笔记:
除非您准备好在每次升级到新的 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')) { $_ } }
Run Code Online (Sandbox Code Playgroud)
-ErrorAction SilentlyContinue请注意从到 的切换-ErrorAction Ignore:后者悄悄地丢弃任何错误,而前者不显示错误,但仍将它们记录在自动$Error变量中,该变量是所有(非忽略的)错误的会话范围集合。
这利用了这样一个事实:该Microsoft.Win32.RegistryKey.GetValue()方法会悄悄地忽略检索不存在值的数据的尝试并返回$null。
顺便说一句:将公共-ErrorAction参数应用于Where-Object( ?) 和ForEach-Object( %) cmdlet 实际上是没有意义的,因为该参数不会应用于在传递给这些命令的脚本块( ) 内运行的代码{ ... }。
Set-StrictModewith-Version 2或更高级别(包括Latest)会导致尝试访问对象上不存在的属性以报告语句终止错误。
请注意,这意味着默认情况下仅终止手头的语句,而整个脚本执行将继续。
另请注意,这-Off是默认值;也就是说,默认情况下不执行严格性检查,这意味着即使尝试引用不存在的变量,默认情况下也不会触发错误;Set-StrictMode -Version 1检查不存在的变量,但不检查不存在的属性。
有几种方法可以避免此类错误:
在属性访问周围使用Try/Catch语句,如CFou 的回答所示;这也使得在没有属性的情况下指定默认值变得很容易,但是与下面基于反射的方法相比,捕获异常的速度很慢:
$o = [pscustomobject] @{ foo = 1 }
$propValue = try { $o.NoSuchProperty } catch { 'default value' }
Run Code Online (Sandbox Code Playgroud)
暂时在子作用域中禁用严格模式(这与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 }
Run Code Online (Sandbox Code Playgroud)
.psobject.Properties通过所有对象上可用的隐藏成员,使用反射来测试属性的存在;这是最快的方法:
$o = [pscustomobject] @{ foo = 1 }
$propValue = if ($o.psobject.Properties['NoSuchProperty']) { $o.NoSuchProperty }
Run Code Online (Sandbox Code Playgroud)
在PowerShell [Core] 7.1+中,您可以通过null 条件运算?.符更简洁地执行此操作:
$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
Run Code Online (Sandbox Code Playgroud)
?.:如果直接应用于变量,则必须意外地将其名称括在{...},例如${var}?.Property;$var?.Property无法按预期工作,因为 PowerShell 假定变量名称为var?- 请参阅GitHub 问题 #11379以尝试更改它。类似地,空合并运算符??(它本身在 v7.0 中可用)可以简化提供默认值的过程(在早期版本中,您可以通过向上面的语句添加else分支来实现if):
$o = [pscustomobject] @{ foo = 1 }
# The RHS of `??` is used if the LHS evaluates to $null.
$propValue = $o.psobject.Properties['NoSuchProperty']?.Value ?? 'default value'
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1046 次 |
| 最近记录: |