¿La mejor manera de verificar si existe un objeto PowerShell?

90

Estoy buscando la mejor manera de verificar si existe un objeto Com.

Aquí está el código que tengo; Me gustaría mejorar la última línea:

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

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

Respuestas:

114

Me gustaría seguir con el $nullcheque, ya que cualquier valor distinto ''(cadena vacía), 0, $falsey $nullse pasa a la verificación: if ($ie) {...}.

Keith Hill
fuente
1
Para usar if ($ val) {...} es mejor para booleanos Todas las demás comprobaciones deben ser if ($ val -ne $ null) {..} Probado yo mismo. TY @Keith Hill
Ilya Gurenko
65

Tu tambien puedes hacer

if ($ie) {
    # Do Something if $ie is not null
}
ravikanth
fuente
4
Me gusta esta opción y su negaciónif (-not $ie) { # Do something if $ie doesn't exist/is falsey }
Chris Magnuson
16

En su ejemplo particular, tal vez no tenga que realizar ninguna verificación . ¿Es posible que New-Objectdevuelva nulo? Nunca he visto eso. El comando debería fallar en caso de un problema y el resto del código en el ejemplo no se ejecutará. Entonces, ¿por qué deberíamos hacer esas comprobaciones?

Solo en el código como a continuación necesitamos algunas verificaciones (la comparación explícita con $ null es la mejor):

# 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
fuente
1
Si el tipo de objeto COM no existe, New-Object lanzará una excepción. Pero no veo cómo podría devolver un valor nulo. Además, ignorar la excepción solo para luego probar nulo es una mala forma.
JasonMArcher
@JasonMArcher: Estoy de acuerdo con el último comentario, absolutamente. Pero realmente, ¿qué esperarías que escribiera en el ejemplo de demostración? Además, dependiendo de un escenario, incluso este código podría estar bien.
Roman Kuzmin
Esencialmente, ponga todo el código que usa $ ie dentro del try {}. De esa forma, se salta si hay una excepción.
JasonMArcher
2
Entonces no sería el código que muestra un caso cuando necesitemos verificar $ null.
Roman Kuzmin
10

Lo que no destacan todas estas respuestas es que al comparar un valor con $ null, debe poner $ null en el lado izquierdo; de lo contrario, puede tener problemas al comparar con un valor de tipo colección. Ver: 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"
}

El bloque anterior se ejecuta (desafortunadamente). Lo que es aún más interesante es que en Powershell un $ value puede ser $ null y no $ null:

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

Por eso es importante poner $ null en el lado izquierdo para que estas comparaciones funcionen con colecciones:

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

¡Supongo que esto muestra una vez más el poder de Powershell!

Dag Wieers
fuente
Sorprendido, esta respuesta no está más votada, ya que contiene el detalle crítico de poner $nullen el lado izquierdo
sonyisda1
1

La verificación de tipo con el operador -is devuelve falso para cualquier valor nulo. En la mayoría de los casos, si no en todos, $ value -is [System.Object] será verdadero para cualquier posible valor no nulo. (En todos los casos, será falso para cualquier valor nulo).

Mi valor no es más que un objeto.

Aron
fuente
1
O incluso $value -is [__ComObject]
Dave_J
0

En caso de que sea como yo y aterrizó aquí tratando de encontrar una manera de saber si su variable de PowerShell es este sabor particular de inexistente:

No se puede utilizar el objeto COM que se ha separado de su RCW subyacente.

Entonces aquí hay un código que funcionó para mí:

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

ejemplo de uso:

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

mezclados con las mejores respuestas de otras personas:

y algunas otras cosas interesantes que debes saber:

Gregor y
fuente