【问题标题】:Powershell returns null instead of an exception when accessing COM property that fails访问失败的 COM 属性时,Powershell 返回 null 而不是异常
【发布时间】:2020-05-08 20:04:48
【问题描述】:

我有以下 COM 接口和实现该接口的 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

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

【问题讨论】:

    标签: powershell exception error-handling null com


    【解决方案1】:

    请注意,此解决方案并非特定于 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 在 PowerShell 端向您的 COM 对象添加一个ScriptMethod,以在访问该属性之前检查该属性是否存在。再次以之前的 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相同的逻辑,而无需修改中的对象- 初始化后的飞行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-03
      • 1970-01-01
      相关资源
      最近更新 更多