Powershell 使用if语句检查变量是否为null返回的结果不正确

Powershell 使用if语句检查变量是否为null返回的结果不正确,powershell,variables,error-handling,Powershell,Variables,Error Handling,我有一个我创建的powershell脚本,其中有一个步骤,它会尝试导入尚未导入的模块 Try { Import-Module -Name 'ModuleName' -ErrorAction Stop -ErrorVariable ModFail } Catch { Write-Error "Module failed to be loaded." } 稍后在脚本中,我将尝试检查模块是否导入失败,但检查错误变量。对于其他未通过errorvariable参

我有一个我创建的powershell脚本,其中有一个步骤,它会尝试导入尚未导入的模块

Try {
    Import-Module -Name 'ModuleName' -ErrorAction Stop -ErrorVariable ModFail             
}
Catch {
    Write-Error "Module failed to be loaded."
}
稍后在脚本中,我将尝试检查模块是否导入失败,但检查错误变量。对于其他未通过errorvariable参数设置的变量,我只使用下面的参数检查其是否为null

If ($null -eq $var) {
    Do stuff
}
但是使用errorvariable设置的变量这样做是不起作用的

if ($null -ne $Modfail) {
    Do stuff
}
当测试变量是否为空时,上面的计算结果为真。这与我想要的正好相反。当我运行这个变量时,它确实是空的并且正在运行

$modfail | Gm 

失败,因为它是空的。为什么会这样?如果我将变量设置在errorvariable参数之外,或者不将其全部设置,它将返回正确的结果。即使它有空格,当管道传输到获取成员时,它也应该作为字符串正确返回?

您可以检查错误变量的真实性:

if( !$ModFail ){
  # Do stuff if the module loaded correctly
}
您不想检查$null-eq$ModFail,因为-ErrorVariable总是设置为集合,尽管如果没有发生错误,则设置为空。集合本身不是null,因此此检查将始终返回$true

由于它是一个集合,您还可以检查-error变量的计数,以确定集合中是否存在任何错误。在您的案例中使用$ModFail:

if( $ModFail.Count -eq 0 ){
  # Do stuff if the module loaded correctly
}

您可以检查错误变量的真实性:

if( !$ModFail ){
  # Do stuff if the module loaded correctly
}
您不想检查$null-eq$ModFail,因为-ErrorVariable总是设置为集合,尽管如果没有发生错误,则设置为空。集合本身不是null,因此此检查将始终返回$true

由于它是一个集合,您还可以检查-error变量的计数,以确定集合中是否存在任何错误。在您的案例中使用$ModFail:

if( $ModFail.Count -eq 0 ){
  # Do stuff if the module loaded correctly
}
-ErrorVariable与所有-*变量公共参数一样,将从相关流收集的输出报告为实例

除非调用存在语法问题,否则将始终创建System.Collections.ArrayList并将其分配给指定变量,即使没有对象输出到目标流;也就是说,在-ErrorAction的情况下,如果没有发生错误,将创建一个空的System.Collections.ArrayList,它与$null不同

因此,如果$null-ne$Modfail。。。不是正确的测试,因为它将始终返回$true。根据定义,任何对象都不是$null,无论其类型或内容如何

相反,如果$Modfail.Count-gt 0。。。或者,更简单地说,依赖于空集合被隐式强制为$false[1]:如果$Modfail

至于:

$modfail |获取成员失败,因为该成员为空。为什么会这样

无论何时通过管道发送集合,都会对其进行枚举。 枚举空数组不会枚举任何内容,在这种情况下,Get成员正确地抱怨缺少输入

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

如果要使用Get Member检查集合本身,请使用Get Member-InputObject$Modfail-您将看到它的类型是System.Collections.ArrayList。作为非泛型集合,它的元素没有预先确定的类型

[1] 注意,根据单个元素的值,单个元素集合也可能被强制为$false;然而,对于由-ErrorVariable创建的集合(其中包含非空的实例),这并不重要;有关背景信息,请参见的底部部分

-ErrorVariable与所有-*变量公共参数一样,将从相关流收集的输出报告为实例

除非调用存在语法问题,否则将始终创建System.Collections.ArrayList并将其分配给指定变量,即使没有对象输出到目标流;也就是说,在-ErrorAction的情况下,如果没有发生错误,将创建一个空的System.Collections.ArrayList,它与$null不同

因此,如果$null-ne$Modfail。。。不是正确的测试,因为它将始终返回$true。根据定义,任何对象都不是$null,无论其类型或内容如何

相反,如果$Modfail.Count-gt 0。。。或者,更简单地说,依赖于空集合被隐式强制为$false[1]:如果$Modfail

至于:

$modfail |获取成员失败,因为该成员为空。为什么会这样

无论何时通过管道发送集合,都会对其进行枚举。 枚举空数组不会枚举任何内容,在这种情况下,Get成员正确地抱怨缺少输入

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

如果要使用Get Member检查集合本身,请使用Get Member -InputObject$Modfail-您将看到它的类型为System.Collections.ArrayList作为非泛型集合,它的元素没有预先确定的类型


[1] 注意,根据单个元素的值,单个元素集合也可能被强制为$false;然而,对于由-ErrorVariable创建的集合(其中包含非空的实例),这并不重要;有关背景信息,请参阅的底部部分。

在测试您的示例时,就我所知,它工作正常。您是否在不同的函数、模块或其他内部/外部的不同作用域中调用$modfail?您可以始终删除-ErrorVariable并将其作为catch块$Modfail=$\的第一行,以查看它是否有区别。不,它全部位于同一主if块中,这只是一个子if块,用于在执行其他工作之前检查变量是否为null。只是再运行一次,得到了相同的结果$null-eq$ModFail返回False,$null-ne$ModFail返回True,即使其值为null。我确实发现运行[String]::IsNullOrWhiteSpace$modFail返回正确,但对于为什么另一种方法不起作用,我仍然很好奇。在测试您的示例时,我发现它工作得很好。您是否在不同的函数、模块或其他内部/外部的不同作用域中调用$modfail?您可以始终删除-ErrorVariable并将其作为catch块$Modfail=$\的第一行,以查看它是否有区别。不,它全部位于同一主if块中,这只是一个子if块,用于在执行其他工作之前检查变量是否为null。只是再运行一次,得到了相同的结果$null-eq$ModFail返回False,$null-ne$ModFail返回True,即使其值为null。我确实发现运行[String]::IsNullOrWhiteSpace$modFail返回正确,但对于另一种方法不起作用的原因,我仍然很好奇。总结一下讨论:使用数组值LHS的-eq测试按设计工作,但可能会让人惊讶:使用数组值LHS的-eq等比较运算符充当数组过滤器,因此,得到的是匹配项的子数组,而不是布尔值。$null-eq@*>&1是$true,而$null-eq@是不正确的,闻起来像个bug-请参阅。我建议清理这里的其他注释,我已经删除了我的注释。总结一下讨论:使用数组值LHS的-eq测试按设计工作,尽管这可能会令人惊讶:使用数组值LHS的-eq等比较运算符充当数组过滤器,因此您得到的结果是匹配项的子数组,而不是布尔值。$null-eq@*>&1是$true,而$null-eq@是不正确的,闻起来像个bug-请参阅。我建议清理这里的其他评论,我已经删除了我的评论。