使用 if 语句检查变量是否为空返回错误

Kee*_*tle 1 variables error-handling powershell

我有一个我创建的 powershell 脚本,如果模块尚未导入,它会尝试导入模块。

Try {
    Import-Module -Name 'ModuleName' -ErrorAction Stop -ErrorVariable ModFail             
}
Catch {
    Write-Error "Module failed to be loaded."
}
Run Code Online (Sandbox Code Playgroud)

稍后在脚本中,我试图检查模块是否无法导入,但检查错误变量。对于未通过 errorvariable 参数设置的其他变量,我仅使用以下内容来检查其是否为空。

If ($null -eq $var) {
    Do stuff
}
Run Code Online (Sandbox Code Playgroud)

但是使用我使用 errorvariable 设置的变量这样做是行不通的。

if ($null -ne $Modfail) {
    Do stuff
}
Run Code Online (Sandbox Code Playgroud)

在测试变量是否实际上为空时,上述评估为真。这与我想要的相反。当我运行变量时,它确实为空并且正在运行

$modfail | Gm 
Run Code Online (Sandbox Code Playgroud)

失败,因为它是空的。为什么会这样?如果我在 errorvariable 参数之外设置变量或者不设置它,它会返回正确的。即使它有空格,它也应该在管道到 Get-Member 时以正确的字符串返回?

mkl*_*nt0 6

  • -ErrorVariable 常见的参数,像所有的-*Variable常用参数,报告从相关数据流作为收集输出的System.Collections.ArrayList实例。

  • (除非有一个句法问题与调用),一个System.Collections.ArrayList总是创建并分配给指定变量,即使没有对象被输出至目标流; 也就是说,在 的情况下-ErrorAction,如果没有发生错误,则会创建一个 System.Collections.ArrayList- 这与 不同$null

因此,if ($null -ne $Modfail) ...不是正确的测试,因为它总是会返回$true(根据定义$null,任何对象都不是,无论其类型或内容如何)。

相反,使用if ($Modfail.Count -gt 0) ...或者更简单地依赖于一个空集合被隐式强制转换为$false[1]的事实:if ($Modfail) ...


至于:

$modfail | Get-Member失败,因为它是空的。为什么会这样?

每当您通过管道发送集合时,它都会被枚举。枚举数组不会枚举任何内容,在这种情况下Get-Member(理所当然地)会抱怨缺少输入。

(如果数组不为空,您应该会看到有关 的信息System.Management.Automation.ErrorRecord,即存储在 中的元素的类型$ModFail)。

如果你想检查集合本身Get-Member,使用
Get-Member -InputObject $Modfail-你会发现它的类型 System.Collections.ArrayList(如非泛型集合,它的元素都没有预定类型)。


[1] 请注意,根据单个元素的值,可以强制使用单元素集合;但是,对于由 所创建的集合,其中包含非空实例,这不是问题;有关背景信息,请参阅此答案的底部部分。$false-ErrorVariableSystem.Management.Automation.ErrorRecord