访问失败的 COM 属性时,Powershell 返回 null 而不是异常

标签 powershell exception error-handling null com

我有以下 COM 接口(interface)和实现此接口(interface)的 COM 对象:

[
    object,
    uuid(8FF1207F-24DD-4F34-B6CB-D90904CF4094),
    dual
]
interface IThrowingProperty : IDispatch
{
    [id(1), propget]
    HRESULT IntPropertyValue([out, retval] int* pVal);
}

[
    uuid(3869048C-A14F-4536-9FFC-0A4ECAEF2B08)
]
coclass ThrowingProperty
{
    [default] interface IThrowingProperty;
};

此属性始终返回错误:
STDMETHODIMP CThrowingProperty::get_IntPropertyValue(/*[out,retval]*/ int* pVal)
{
    return E_NOTIMPL;
}

但是当我尝试在 Powershell 中访问它时,我没有收到任何错误,并且属性值等于 $null:
$PropertyWillThrow = New-Object -ComObject "PowershellCom.ThrowingProperty"
$PropertyWillThrow.IntPropertyValue
$PropertyWillThrow.IntPropertyValue -eq $null

enter image description here

是否可以在不将属性更改为方法的情况下从 Powershell 中的 COM 属性中获取错误?
谢谢

最佳答案

请注意,此解决方案并非特定于 COM 对象,而是适用于 PowerShell 中的任何对象类型。

它不会抛出错误,它只会返回 $null .这是 PowerShell 在访问对象上不存在的属性时的正常行为。但是,您可以通过以下代码检查该属性是否真正定义在对象上。针对 Excel COM 对象进行测试:

 # Returns true if property exists
 $excel = New-Object -ComObject Excel.Application
 [bool]( $excel.PSobject.Properties.Name -match 'EnableCheckFileExtensions' ) # ==> True
 [bool]( $excel.PSobject.Properties.Name -match 'NonExistentPropertyName' ) # ====> False
EnableCheckFileExtensionsMicrosoft.Office.Interop.Excel.ApplicationClass 上的属性类型,所以它返回 true,但是 NonExistantPropertyName不存在,因此评估返回 false。

如果你想要一个错误驱动的行为,你可以使用 Add-Member 添加 ScriptMethod到 PowerShell 端的 COM 对象,以在访问该属性之前检查该属性是否存在。再次以之前的 Excel COM 对象为例:
$checkPropertyExistsBlock = {
  Param(
    [string]$memberName
  )

  if( [bool]( $This.PSobject.Properties.Name -match $memberName ) ) {
    $This.$memberName
  } else {
    throw "Property ${memberName} does not exist" 
  }
}
$excel | Add-Member -MemberType ScriptMethod -Name 'GetPropertyByName' -Value $checkPropertyExistsBlock

$excel.GetPropertyByName( 'EnableCheckFileExtensions' ) # ==> Returns property value
$excel.GetPropertyByName( 'NonExistentPropertyName' ) # ====> throws exception

当然,如果你自己控制类的源代码,你也可以添加GetPropertyByName作为类的方法,并使用反射来实现与 ScriptBlock 相同的逻辑上面,而不必在初始化后修改运行中的对象。

关于访问失败的 COM 属性时,Powershell 返回 null 而不是异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59863506/

相关文章:

.net - 当参数相互冲突时抛出什么最合适的异常?

vb.net - 为不存在的数组项设置值?

php - 未定义Codeigniter uri。在首页上损坏,在搜索页上很好

asp.net - 如何防止 ASP.NET 记录身份验证失败?

powershell - Dynamics CRM导出解决方案(非本地)

.net - 创建没有密码的 PSCredential

powershell - 为什么我需要先在 PowerShell 脚本中编写函数?

powershell - 在 PowerShell 中替换后如何管道?

c++ - 谁取得 IErrorInfo 的所有权?

ios - 不符合协议(protocol)错误