Najlepszy sposób sprawdzenia, czy istnieje obiekt programu PowerShell?

92

Szukam najlepszego sposobu sprawdzenia, czy obiekt Com istnieje.

Oto kod, który mam; Chciałbym poprawić ostatnią linię:

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

$ie -ne $null #Are there better options?
LaPhi
źródło

Odpowiedzi:

115

Chciałbym pozostać przy $nullzameldowaniu od każdej wartości innej niż ''(pusty ciąg znaków) 0, $falsea $nullprzejdzie sprawdzanie: if ($ie) {...}.

Keith Hill
źródło
1
Aby użyć if ($ val) {...} jest lepsze dla wartości logicznych. Wszystkie inne sprawdzenia powinny być przeprowadzone, jeśli ($ val -ne $ null) {..} Przetestowałem się. TY @Keith Hill
Ilya Gurenko
68

Ty też możesz to zrobić

if ($ie) {
    # Do Something if $ie is not null
}
ravikanth
źródło
4
Podoba mi się ta opcja i jej zaprzeczenieif (-not $ie) { # Do something if $ie doesn't exist/is falsey }
Chris Magnuson
16

W twoim konkretnym przykładzie być może nie musisz w ogóle wykonywać żadnych kontroli . Czy to możliwe, że New-Objectzwrot null? Nigdy tego nie widziałem. Polecenie powinno zakończyć się niepowodzeniem w przypadku problemu, a reszta kodu w przykładzie nie zostanie wykonana. Dlaczego więc w ogóle mielibyśmy robić to kontrole?

Tylko w kodzie jak poniżej potrzebujemy pewnych sprawdzeń (najlepsze jest jawne porównanie z $ 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) {
    ...
}
Roman Kuzmin
źródło
1
Jeśli typ obiektu COM nie istnieje, New-Object zgłosi wyjątek. Ale nie rozumiem, jak może zwrócić wartość zerową. Ponadto ignorowanie wyjątku tylko w celu sprawdzenia wartości null jest złą formą.
JasonMArcher
@JasonMArcher: Absolutnie zgadzam się z ostatnią uwagą. Ale tak naprawdę, czego spodziewałbyś się, że napiszę w przykładzie demonstracyjnym? Poza tym, w zależności od scenariusza, nawet ten kod może być w porządku.
Roman Kuzmin
Zasadniczo cały kod używający znaku $ ie należy umieścić wewnątrz try {}. W ten sposób jest pomijany, jeśli jest wyjątek.
JasonMArcher
2
Wtedy nie byłby to kod pokazujący przypadek, kiedy musimy sprawdzić $ null.
Roman Kuzmin
11

Wszystkie te odpowiedzi nie podkreślają tego, że porównując wartość z $ null, musisz umieścić $ null po lewej stronie, w przeciwnym razie możesz mieć kłopoty podczas porównywania z wartością typu kolekcji. Zobacz: 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"
}

Powyższy blok jest (niestety) wykonywany. Jeszcze bardziej interesujące jest to, że w Powershell wartość $ może być równa $ null i nie $ null:

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

Dlatego ważne jest, aby umieścić $ null po lewej stronie, aby te porównania działały z kolekcjami:

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

Wydaje mi się, że to po raz kolejny pokazuje moc Powershell!

Dag Wieers
źródło
Zaskoczony, ta odpowiedź nie jest bardziej pozytywna, ponieważ zawiera krytyczny szczegół dotyczący umieszczenia $nullpo lewej stronie
sonyisda1
1

Sprawdzanie typu z operatorem -is zwraca false dla dowolnej wartości null. W większości przypadków, jeśli nie wszystkie, $ value -is [System.Object] będzie prawdziwe dla każdej możliwej wartości innej niż null. (We wszystkich przypadkach będzie to fałsz dla każdej wartości null).

Moja wartość jest niczym, jeśli nie przedmiotem.

Aron
źródło
1
Albo nawet $value -is [__ComObject]
Dave_J,
0

Załóżmy, że jesteś podobny do mnie i wylądowałeś tutaj, próbując znaleźć sposób, aby stwierdzić, czy twoja zmienna PowerShell ma ten szczególny smak nieistniejący:

Nie można użyć obiektu COM, który został oddzielony od jego podstawowego RCW.

Oto kod, który zadziałał dla mnie:

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

przykład użycia:

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

zmiksowane z lepszymi odpowiedziami innych ludzi:

i kilka innych fajnych rzeczy, które warto wiedzieć:

Gregor y
źródło