Лучший способ проверить, существует ли объект PowerShell?

92

Я ищу лучший способ проверить, существует ли Com-объект.

Вот код, который у меня есть; Я бы хотел улучшить последнюю строчку:

$ie = New-Object -ComObject InternetExplorer.Application
$ie.Navigate("http://www.stackoverflow.com")
$ie.Visible = $true

$ie -ne $null #Are there better options?
ЛаФи
источник

Ответы:

115

Я хотел бы придерживаться с $nullпроверкой , так как любое значение , отличное ''(пустая строка), 0, $falseи $nullбудет проходить проверку: if ($ie) {...}.

Кейт Хилл
источник
1
Использовать if ($ val) {...} лучше для логических значений. Все остальные проверки должны выполняться if ($ val -ne $ null) {..} Проверял сам. TY @Keith Hill
Илья Гуренко
68

Вы также можете сделать

if ($ie) {
    # Do Something if $ie is not null
}
равикант
источник
4
Мне нравится этот вариант и его отрицаниеif (-not $ie) { # Do something if $ie doesn't exist/is falsey }
Крис Магнусон
16

В вашем конкретном примере, возможно, вам вообще не нужно выполнять какие-либо проверки . Возможно ли, что New-Objectвозврат null? Я такого никогда не видел. Команда должна завершиться ошибкой в ​​случае возникновения проблемы, и остальной код в примере не будет выполнен. Так зачем нам вообще проводить эти проверки?

Только в приведенном ниже коде нам нужны некоторые проверки (лучше всего явное сравнение с $ null):

# we just try to get a new object
$ie = $null
try {
    $ie = New-Object -ComObject InternetExplorer.Application
}
catch {
    Write-Warning $_
}

# check and continuation
if ($ie -ne $null) {
    ...
}
Роман Кузьмин
источник
1
Если тип COM-объекта не существует, New-Object вызовет исключение. Но я не понимаю, как он мог вернуть нуль. Кроме того, игнорирование исключения только для проверки на null - это плохой тон.
JasonMArcher
@JasonMArcher: Абсолютно согласен с последним замечанием. Но на самом деле, что вы ожидаете, что я напишу в демонстрационном примере? Кроме того, в зависимости от сценария даже этот код может подойти.
Роман Кузьмин
По сути, поместите весь код, который использует $ ie, внутрь try {}. Таким образом, в случае исключения он пропускается.
JasonMArcher
2
Тогда это не будет код, показывающий случай, когда нам нужно проверить $ null.
Роман Кузьмин
11

Все эти ответы не подчеркивают, что при сравнении значения с $ null вы должны поместить $ null в левую часть, иначе у вас могут возникнуть проблемы при сравнении со значением типа коллекции. См. Https://github.com/nightroman/PowerShellTraps/blob/master/Basic/Comparison-operators-with-collections/looks-like-object-is-null.ps1

$value = @(1, $null, 2, $null)
if ($value -eq $null) {
    Write-Host "$value is $null"
}

Вышеупомянутый блок (к сожалению) выполнен. Что еще более интересно, в Powershell значение $ может быть как $ null, так и не $ null:

$value = @(1, $null, 2, $null)
if (($value -eq $null) -and ($value -ne $null)) {
    Write-Host "$value is both $null and not $null"
}

Поэтому важно поставить $ null в левой части, чтобы эти сравнения работали с коллекциями:

$value = @(1, $null, 2, $null)
if (($null -eq $value) -and ($null -ne $value)) {
    Write-Host "$value is both $null and not $null"
}

Думаю, это еще раз демонстрирует мощь Powershell!

Даг Вирс
источник
Удивлен, что этот ответ не получил больше голосов, так как он содержит важную деталь о том, как надевать $nullлевую часть
sonyisda1 01
1

Проверка типа с оператором -is возвращает false для любого значения NULL. В большинстве случаев, если не во всех, $ value -is [System.Object] будет истинным для любого возможного ненулевого значения. (Во всех случаях он будет ложным для любого нулевого значения.)

Моя ценность ничто, если не объект.

Арон
источник
1
Или даже $value -is [__ComObject]
Dave_J
0

Если вы похожи на меня, и вы приземлились здесь, пытаясь найти способ определить, является ли ваша переменная PowerShell этим конкретным вариантом несуществующего:

COM-объект, который был отделен от основного RCW, использовать нельзя.

Тогда вот код, который у меня сработал:

function Count-RCW([__ComObject]$ComObj){
   try{$iuk = [System.Runtime.InteropServices.Marshal]::GetIUnknownForObject($ComObj)}
   catch{return 0}
   return [System.Runtime.InteropServices.Marshal]::Release($iuk)-1
}

пример использования:

if((Count-RCW $ExcelApp) -gt 0){[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($ExcelApp)}

собраны вместе из лучших ответов других людей:

и еще кое-что интересное:

Грегор у
источник