我正在寻找检查 Com 对象是否存在的最佳方法。
这是我的代码;我想改进最后一行:
$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) {...}
。
你也可以做
if ($ie) {
# Do Something if $ie is not null
}
所有这些答案都没有强调的是,当将值与
$null
进行比较时,必须将$null
放在左侧,否则在与集合类型值进行比较时可能会遇到麻烦。请参阅: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"
}
上面的块(不幸的是)被执行了。更有趣的是,在 PowerShell 中 $value 可以是
$null
和 !$null
:
$value = @(1, $null, 2, $null)
if (($value -eq $null) -and ($value -ne $null)) {
Write-Host "$value is both $null and not $null"
}
因此,将
$null
放在左侧非常重要,以使这些比较适用于集合:
$value = @(1, $null, 2, $null)
if (($null -eq $value) -and ($null -ne $value)) {
Write-Host "$value is both $null and not $null"
}
我想这再次显示了 PowerShell 的强大功能!
在您的特定示例中,也许您根本不必执行任何检查。
New-Object
有可能返回null吗?我从来没有见过这样的情况。如果出现问题,该命令应该会失败,并且示例中的其余代码将不会执行。那么我们为什么要进行这样的检查呢?
只有在下面的代码中我们需要一些检查(与 $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) {
...
}
使用 -is 运算符进行类型检查对于任何 null 值都会返回 false。 在大多数情况下(如果不是全部),$value -is [System.Object] 对于任何可能的非空值都将为 true。 (在所有情况下,任何空值都将为 false。)
如果不是一个物体,我的价值就什么都不是。
我相信这个问题(尽管很老)确实是一个问题 检查空值。 检查空值(或非空值) PowerShell 很棘手。 使用 ($null -eq $value) 或 ($null -ne $value) 并不总是有效。 if($value) 也没有。使用它们 甚至可能会在以后引起问题。
只需阅读下面这篇 Microsoft 文章(全文)即可掌握 Powershell 中的 null 值有多么棘手。[https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-null?view=powershell-7.1][1]
我在下面编写了这两个函数来检查空(或非空)值 在 PowerShell 中。 我“相信”他们应该为任何和所有价值观而努力 和数据类型。
我希望有人觉得它们有帮助。 我不知道为什么 MS 没有将这样的东西本地放入 PowerShell 中 使在 PowerShell 中处理 null 变得更容易(并且危险性更小)。
我希望这对某人有帮助。
如果有人知道这种方法有一个看不见的“陷阱”或问题, 请在这里发表评论,以便我们了解这一点。 谢谢!
<#
*********************
FUNCTION: ValueIsNull
*********************
Use this function ValueIsNull below for checking for null values
rather using -eq $null or if($value) methods. Those may not work as expected.
See reference below for more details on $null values in PowerShell.
[https://learn.microsoft.com/en-us/powershell/scripting/learn/deep-dives/everything-about-null?view=powershell-7.1][1]
An if statement with a call to ValueIsNull can be written like this:
if (ValueIsNull($TheValue))
#>
function ValueIsNull {
param($valueToCheck)
# In Powershell when a parameter of a function does not have a data type defined,
# it will create the parameter as a PSObject. It will do this for
# an object, an array, and a base date type (int, string, DateTime, etc.)
# However if the value passed in is $null, then it will still be $null.
# So, using a function to check null gives us the ability to determine if the parameter
# is null or not by checking if the parameter is a PSObject or not.
# This function could be written more efficiently, but intentionally
# putting it in a more readable format.
# Special Note: This cannot tell the difference between a parameter
# that is a true $null and an undeclared variable passed in as the parameter.
# ie - If you type the variable name wrong and pass that in to this function it will see it as a null.
[bool]$returnValue = $True
[bool]$isItAnObject=$True
[string]$ObjectToString = ""
try { $ObjectToString = $valueToCheck.PSObject.ToString() } catch { $isItAnObject = $false }
if ($isItAnObject)
{
$returnValue=$False
}
return $returnValue
}
<#
************************
FUNCTION: ValueIsNotNull
************************
Use this function ValueIsNotNull below for checking values for
being "not-null" rather than using -ne $null or if($value) methods.
Both may not work as expected.
See notes on ValueIsNull function above for more info.
ValueIsNotNull just calls the ValueIsNull function and then reverses
the boolean result. However, having ValueIsNotNull available allows
you to avoid having to use -eq and\or -ne against ValueIsNull results.
You can disregard this function and just use !ValueIsNull($value).
But, it is my preference to have both for easier readability of code.
An if statement with a call to ValueIsNotNull can be written like this:
if (ValueIsNotNull($TheValue))
#>
function ValueIsNotNull {
param($valueToCheck)
[bool]$returnValue = !(ValueIsNull($valueToCheck))
return $returnValue
}
您可以使用以下对 ValueIsNull 的调用列表来测试它。
$psObject = New-Object PSObject
Add-Member -InputObject $psObject -MemberType NoteProperty -Name customproperty -Value "TestObject"
$valIsNull = ValueIsNull($psObject)
$props = @{
Property1 = 'one'
Property2 = 'two'
Property3 = 'three'
}
$otherPSobject = new-object psobject -Property $props
$valIsNull = ValueIsNull($otherPSobject)
# Now null the object
$otherPSobject = $null
$valIsNull = ValueIsNull($otherPSobject)
# Now an explicit null
$testNullValue = $null
$valIsNull = ValueIsNull($testNullValue)
# Now a variable that is not defined (maybe a type error in variable name)
# This will return a true because the function can't tell the difference
# between a null and an undeclared variable.
$valIsNull = ValueIsNull($valueNotDefine)
[int32]$intValueTyped = 25
$valIsNull = ValueIsNull($intValueTyped)
$intValueLoose = 67
$valIsNull = ValueIsNull($intValueLoose)
$arrayOfIntLooseType = 4,2,6,9,1
$valIsNull = ValueIsNull($arrayOfIntLooseType)
[int32[]]$arrayOfIntStrongType = 1500,2230,3350,4000
$valIsNull = ValueIsNull($arrayOfIntStrongType)
#Now take the same int array variable and null it.
$arrayOfIntStrongType = $null
$valIsNull = ValueIsNull($arrayOfIntStrongType)
$stringValueLoose = "String Loose Type"
$valIsNull = ValueIsNull($stringValueLoose)
[string]$stringValueStrong = "String Strong Type"
$valIsNull = ValueIsNull($stringValueStrong)
$dateTimeArrayLooseValue = @("1/1/2017", "2/1/2017", "3/1/2017").ForEach([datetime])
$valIsNull = ValueIsNull($dateTimeArrayLooseValue)
# Note that this has a $null in the array values. Still returns false correctly.
$stringArrayLooseWithNull = @("String1", "String2", $null, "String3")
$valIsNull = ValueIsNull($stringArrayLooseWithNull)
我也有同样的问题。这个解决方案对我有用。
$Word = $null
$Word = [System.Runtime.InteropServices.Marshal]::GetActiveObject('word.application')
if ($Word -eq $null)
{
$Word = new-object -ComObject word.application
}
如果你像我一样,来到这里试图找到一种方法来判断你的 PowerShell 变量是否是这种不存在的特殊类型:
已经与其底层RCW分离的COM对象不能被 使用过。
然后这是一些对我有用的代码:
function Count-RCW([__ComObject]$ComObj){
try{$iuk = [System.Runtime.InteropServices.Marshal]::GetIUnknownForObject($ComObj)}
catch{return 0}
return [System.Runtime.InteropServices.Marshal]::Release($iuk)-1
}
用法示例:
if((Count-RCW $ExcelApp) -gt 0){[System.Runtime.InteropServices.Marshal]::FinalReleaseComObject($ExcelApp)}
从其他人更好的答案中综合起来:
以及其他一些很酷的事情要知道:
要在实例化的 PsObject 上使用 if 语句进行测试(如下所示),您可以使用以下命令。如果您使用不同类型的对象,则必须调整大于旁边的值
$tempObject = New-Object -TypeName PsObject;
if (($tempObject | Get-Member).Count -gt 4)
$tempObject |获取会员
类型名称:System.Management.Automation.PSCustomObject
名称成员类型定义
---- ---------- ---------- Equals 方法 bool Equals(System.Object obj) GetHashCode 方法 int GetHashCode() GetType 方法类型 GetType()
ToString 方法 字符串 ToString()
如果不使用 try .. catch,如果 COM 对象不存在,则不可避免地会显示错误消息... 以下代码不显示任何错误消息:
try {
$ie = New-Object -ComObject InternetExplorer.Application
}
catch {
$ie = $null
}
# check and continuation
if (!$ie) {
...
}