использование оператора if для проверки, что переменная равна нулю, возвращает неверно - PullRequest
1 голос
/ 16 января 2020

У меня есть сценарий 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
}

при проверке, действительно ли переменная равна нулю, приведенное выше значение равно true. Это противоположность того, что я хочу. Когда я запускаю переменную, она действительно равна нулю, и запуск

$modfail | Gm 

завершается ошибкой, потому что она пуста. Почему это происходит? Если я устанавливаю переменную вне параметра errorvariable или не устанавливаю ее, все возвращается правильно. Даже если у него есть пробел, он должен возвращаться в виде правильной строки при передаче в Get-Member?

Ответы [ 2 ]

5 голосов
/ 16 января 2020
  • Общий параметр -ErrorVariable , как и все общие параметры -*Variable, сообщает собранные выходные данные из соответствующего потока как экземпляр System.Collections.ArrayList .

  • (Если только нет проблемы syntacti c с вызовом), System.Collections.ArrayList это всегда , созданная и назначенная для указанная переменная, даже если объекты no выводятся в целевой поток; то есть в случае -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 (поскольку коллекция c не является универсальной, ее элементы не имеют заранее определенного типа).


[1] Обратите внимание, что одноэлементных коллекций может также приводиться к $false, в зависимости от значения этого одиночного элемент; однако с коллекциями, созданными -ErrorVariable, которые содержат System.Management.Automation.ErrorRecord случаев, когда они не пустые, это не проблема; дополнительную информацию см. в нижнем разделе этого ответа .

0 голосов
/ 16 января 2020

Вместо этого вы можете проверить достоверность переменной error:

if( !$ModFail ){
  # Do stuff if the module loaded correctly
}

Вы не хотите проверять if( $null -eq $ModFail ), потому что -ErrorVariable всегда устанавливается в коллекцию, хотя и пустую, если ошибки не возникает. Сама коллекция не является нулевой, поэтому эта проверка всегда будет возвращать $true.

Поскольку она является коллекцией, вы можете также проверить Count из -ErrorVariable для определения наличия ошибок в коллекции. Используя $ModFail в вашем случае:

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