Melhor maneira de verificar se existe um objeto PowerShell?


90

Estou procurando a melhor maneira de verificar se existe um objeto Com.

Aqui está o código que tenho; Eu gostaria de melhorar a última linha:

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

$ie -ne $null #Are there better options?

Respostas:


114

Gostaria de ficar com o $nullcheque uma vez que qualquer valor diferente de ''(string vazia), 0, $falsee $nullvai passar a verificação: if ($ie) {...}.


1
Para usar if ($ val) {...} é melhor para booleanos Todas as outras verificações devem ser if ($ val -ne $ null) {..} Testado por mim mesmo. TY @Keith Hill
Ilya Gurenko

65

Você também pode fazer

if ($ie) {
    # Do Something if $ie is not null
}

4
Eu gosto dessa opção e de sua negaçãoif (-not $ie) { # Do something if $ie doesn't exist/is falsey }
Chris Magnuson,

16

Em seu exemplo particular, talvez você não precise realizar nenhuma verificação . É possível que New-Objectretorne nulo? Eu nunca vi isso. O comando deve falhar no caso de um problema e o resto do código no exemplo não será executado. Então, por que deveríamos fazer essas verificações?

Apenas no código abaixo, precisamos de algumas verificações (a comparação explícita com $ null é a melhor):

# 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
Se o tipo de objeto COM não existir, New-Object lançará uma exceção. Mas não vejo como poderia retornar um nulo. Além disso, ignorar a Exceção apenas para testar o valor nulo é uma forma inadequada.
JasonMArcher

@JasonMArcher: Concordo com a última observação, absolutamente. Mas, realmente, o que você espera que eu escreva no exemplo de demonstração? Além disso, dependendo do cenário, até mesmo esse código pode funcionar bem.
Roman Kuzmin

Basicamente, coloque todo o código que usa $ ie dentro do try {}. Dessa forma, ele será ignorado se houver uma exceção.
JasonMArcher

2
Então, não seria o código mostrando um caso em que precisamos verificar $ null.
Roman Kuzmin

10

O que todas essas respostas não destacam é que, ao comparar um valor com $ null, você deve colocar $ null no lado esquerdo, caso contrário, poderá ter problemas ao comparar com um valor do tipo coleção. Veja: 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"
}

O bloco acima é (infelizmente) executado. O que é ainda mais interessante é que no Powershell um valor $ pode ser $ null e não $ null:

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

Portanto, é importante colocar $ null no lado esquerdo para fazer essas comparações funcionarem com coleções:

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

Acho que isso mostra mais uma vez o poder do Powershell!


Surpreso, essa resposta não foi mais votada, pois contém o detalhe crítico de colocar $nullno lado esquerdo
sonyisda1

1

A verificação de tipo com o operador -is retorna falso para qualquer valor nulo. Na maioria dos casos, se não em todos, $ value -is [System.Object] será verdadeiro para qualquer valor não nulo possível. (Em todos os casos, será falso para qualquer valor nulo.)

Meu valor não é nada senão um objeto.


1
Ou mesmo $value -is [__ComObject]
Dave_J


0

No caso de você ser como eu e aterrissou aqui tentando encontrar uma maneira de dizer se a sua variável do PowerShell é este tipo particular de inexistente:

Objeto COM que foi separado de seu RCW subjacente não pode ser usado.

Então aqui está um código que funcionou para mim:

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

exemplo de uso:

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

misturado com as melhores respostas de outras pessoas:

e algumas outras coisas legais para saber:

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.