Powershell возвращает значение NULL вместо исключения при доступе к свойству COM, которое не удалось - PullRequest
2 голосов
/ 22 января 2020

У меня есть следующий 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

enter image description here

Возможно ли получить ошибку из свойства COM в Powershell без изменения свойства на метод? Спасибо

1 Ответ

0 голосов
/ 22 января 2020

Обратите внимание, что это решение не указано c для COM-объектов, но будет работать с любым типом объектов в PowerShell.

Оно не выдаст ошибку, оно просто вернет $null. Это нормальное поведение для PowerShell при доступе к несуществующему свойству объекта. Однако вы можете проверить, действительно ли свойство определено для объекта, с помощью следующего кода. Тестирование в COM-объекте Excel:

 # 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

EnableCheckFileExtensions - это свойство типа Microsoft.Office.Interop.Excel.ApplicationClass, поэтому оно возвращает значение true, но NonExistantPropertyName не существует, поэтому оценка возвращает значение false.


Если вам нужно поведение, основанное на ошибках, вы можете использовать Add-Member, чтобы добавить ScriptMethod к вашему COM-объекту на стороне PowerShell, чтобы проверить, что свойство существует до доступ к нему. Используя предыдущий COM-объект Excel в качестве примера снова:

$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 в качестве метода для вашего класса и использовать отражение для реализовать тот же лог c, что и ScriptBlock выше, без необходимости изменять объект в полете после его инициализации.

...