DirectoryEntry.MoveTo исключения: абстрагируется от UnsafeNativeMethods, но не документируется - PullRequest
0 голосов
/ 19 декабря 2018

System.DirectoryServices содержит класс / метод DirectoryEntry.MoveTo(..).Единственное зарегистрированное исключение - InvalidOperationException, если целевой DirectoryEntry не является контейнером.Я ожидаю, что будут и другие возможные исключения, особенно с разрешениями.

Под капотом .MoveTo() звонки

DirectoryEntry.ContainerObject.MoveHere(this.Path, newName);

, где DirectoryEntry - новое целевое местоположение,Который вызывает:

internal class UnsafeNativeMethods
{
    [Guid("001677D0-FD16-11CE-ABC4-02608C9E7553")]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    [ComImport]
    public interface IAdsContainer
    {
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Interface)]
        object MoveHere([MarshalAs(UnmanagedType.BStr), In] string sourceName, [MarshalAs(UnmanagedType.BStr), In] string newName);
        ...
    }
    ...
}

Данный GUID относится к библиотеке типов activeds.tlb.Эта библиотека определяет IADsContainer.MoveHere как

[id(0x00000009)]
HRESULT MoveHere(
                [in] BSTR SourceName, 
                [in] BSTR NewName, 
                [out, retval] IDispatch** ppObject);

Разрыв заключается в том, что activeds.dll возвращает HRESULT и дает вызывающей стороне указатель на объект через выходной параметр.Но оболочка .NET имеет другую подпись и не имеет HRESULT.

Два вопроса:

  1. Как UnsafeNativeMethods.IAdsContainer.MoveHere сопоставить интерфейсу COM с другой подписью?
  2. Что происходит с этим HRESULT?

Относительно # 2 ... Если в середине есть объект, который вызывает версию MoveHere для HRESULT, этот объект, скорее всего, проверяет результат и выбрасываетисключение или возврат IAdsContainer, который он создал.Но я понятия не имею, какой объект может быть в середине, и ни код платформы .NET, ни файл .tlb не дают мне никаких подсказок.Любые исключения, которые он создает, не задокументированы.

1 Ответ

0 голосов
/ 19 декабря 2018

Он принимает последний параметр [out, retval] IDispatch** ppObject и возвращает его, интерпретирует возвращенный HRESULT и выдает COMException, если необходимо.Я просто не видел того фактического кода, который делает это.

Я подозреваю, что это атрибут [ComImport], который говорит .NET обрабатывать его по-другому.

На самом деле, исходный код показываетиз-за этого атрибута есть некоторая особая обработка, хотя я не буду притворяться, что полностью понимаю, что происходит.

Например, возьмите метод GetCustomMarshaledCOMObject. Он вызывает GetIUnknown и совершает особую магию, когда возвращается false.

GetIUnknown метод специально проверяет ComImportAttribute и возвращает false если он есть.

Даже метод, который вызывает GetCustomMarshaledCOMObject, говорит:

// Check for COMObject & do some special custom marshaling
...