La meilleure façon de vérifier si un objet PowerShell existe?

90

Je recherche la meilleure façon de vérifier si un objet Com existe.

Voici le code que j'ai; J'aimerais améliorer la dernière ligne:

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

$ie -ne $null #Are there better options?
LaPhi
la source

Réponses:

114

Je tiendrais avec le $nullchèque depuis une valeur autre que ''(chaîne vide), 0, $falseet $nullpassera le contrôle: if ($ie) {...}.

Keith Hill
la source
1
Utiliser if ($ val) {...} est mieux pour les booléens Toutes les autres vérifications devraient être if ($ val -ne $ null) {..} Je me suis testé. TY @Keith Hill
Ilya Gurenko
65

Vous pouvez aussi faire

if ($ie) {
    # Do Something if $ie is not null
}
ravikanth
la source
4
J'aime cette option et sa négationif (-not $ie) { # Do something if $ie doesn't exist/is falsey }
Chris Magnuson
16

Dans votre exemple particulier, vous n'avez peut-être aucun contrôle à effectuer . Est-ce possible queNew-Object retourne null? Je n'ai jamais vu ça. La commande devrait échouer en cas de problème et le reste du code de l'exemple ne sera pas exécuté. Alors pourquoi devrions-nous faire ces vérifications?

Seulement dans le code comme ci-dessous, nous avons besoin de quelques vérifications (la comparaison explicite avec $ null est la meilleure):

# 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
la source
1
Si le type d'objet COM n'existe pas, New-Object lèvera une exception. Mais je ne vois pas comment cela pourrait renvoyer un null. En outre, ignorer l'exception uniquement pour ensuite tester la valeur null est une mauvaise forme.
JasonMArcher
@JasonMArcher: Je suis d'accord avec la dernière remarque, absolument. Mais vraiment, qu'espérez-vous que j'écrive dans l'exemple de démonstration? En outre, selon un scénario, même ce code pourrait être très bien.
Roman Kuzmin
Essentiellement, mettez tout le code qui utilise $ ie dans le try {}. De cette façon, il est ignoré s'il y a une exception.
JasonMArcher
2
Ensuite, ce ne serait pas le code montrant un cas où nous devons vérifier $ null.
Roman Kuzmin
10

Ce que toutes ces réponses ne mettent pas en évidence, c'est que lorsque vous comparez une valeur à $ null, vous devez mettre $ null sur le côté gauche, sinon vous risquez d'avoir des problèmes lors de la comparaison avec une valeur de type collection. Voir: 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"
}

Le bloc ci-dessus est (malheureusement) exécuté. Ce qui est encore plus intéressant, c'est que dans Powershell, une valeur $ peut être à la fois $ null et non $ null:

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

Il est donc important de mettre $ null sur le côté gauche pour que ces comparaisons fonctionnent avec les collections:

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

Je suppose que cela montre encore une fois la puissance de Powershell!

Dag Wieers
la source
Surpris, cette réponse n'est pas plus votée car elle contient le détail critique de la mise $nullsur le côté gauche
sonyisda1
1

La vérification de type avec l'opérateur -is renvoie false pour toute valeur nulle. Dans la plupart des cas, sinon tous, $ value -is [System.Object] sera vrai pour toute valeur non nulle possible. (Dans tous les cas, il sera faux pour toute valeur nulle.)

Ma valeur n'est rien sinon un objet.

Aron
la source
1
Ou même $value -is [__ComObject]
Dave_J
0

Au cas où vous êtes comme moi et vous avez atterri ici en essayant de trouver un moyen de savoir si votre variable PowerShell est cette saveur particulière d'inexistant:

L'objet COM qui a été séparé de son RCW sous-jacent ne peut pas être utilisé.

Ensuite, voici un code qui a fonctionné pour moi:

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

exemple d'utilisation:

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

écrasés à partir des meilleures réponses des autres:

et quelques autres choses intéressantes à savoir:

Gregor y
la source