检查PowerShell对象是否存在的最佳方法是什么?

Best way to check if an PowerShell Object exist?

我正在寻找检查COM对象是否存在的最佳方法。

这是我的代码;我想改进最后一行:

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

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

我会坚持使用$null号支票,因为除''号(空字符串)、0号、$false号和$null号以外的任何值都会通过支票:if ($ie) {...}号。


你也可以这样做

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


在您的特定示例中,可能根本不需要执行任何检查。有没有可能New-Object返回空?我从没见过。如果出现问题,命令应该失败,并且示例中的其余代码将不会执行。那我们为什么要做那些检查呢?

只有在下面这样的代码中,我们需要进行一些检查(最好与$null进行显式比较):

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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) {
    ...
}


所有这些答案都没有突出显示的是,将值与$null进行比较时,必须将$null放在左侧,否则与集合类型值进行比较时可能会遇到问题。请参阅:https://github.com/nightroman/powershelltraps/blob/master/basic/comparison-operators-with-collections/looks-like-object-is-null.ps1

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

上面的块被(不幸地)执行。更有趣的是,在PowerShell中,$值可以是$null,也可以不是$null:

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

因此,重要的是将$null放在左侧,以使这些比较能够与集合一起工作:

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

我想这又显示了PowerShell的威力!


对于任何空值,使用-is运算符进行类型检查时返回false。在大多数情况下,如果不是全部,$value-is[system.object]对于任何可能的非空值都将为true。(在所有情况下,任何空值都将为假。)

如果不是一个对象,我的值就是零。


如果您像我一样,您在这里登陆,试图找到一种方法来判断您的PowerShell变量是否是这种不存在的特殊风格:

COM object that has been separated from its underlying RCW cannot be
used.

下面是一些适用于我的代码:

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

示例用法:

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

从其他人更好的答案中混合而成:

  • 在C中使用COM互操作时的RCW和引用计数#
  • RCW参考计数规则!=COM引用计数规则
  • "已与其基础RCW分离的COM对象不能与.NET 4.0一起使用"

还有一些很酷的事情要知道:

  • 无法使用已与其基础RCW分离的COM对象
  • 定制排列
  • 高级COM互操作性


我也有同样的问题。这个解决方案对我有效。

1
2
3
4
5
6
$Word = $null
$Word = [System.Runtime.InteropServices.Marshal]::GetActiveObject('word.application')
if ($Word -eq $null)
{
    $Word = new-object -ComObject word.application
}

https://msdn.microsoft.com/de-de/library/system.runtime.interopservices.marshal.getActiveObject(v=vs.110).aspx