DirectoryEntry.MoveTo исключения: абстрагируется от UnsafeNativeMethods, но не документируется
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.
Два вопроса:
- Как UnsafeNativeMethods.IAdsContainer.MoveHere может сопоставляться с интерфейсом COM с другой подписью?
- Что происходит с этим HRESULT?
Что касается #2... Если в середине есть объект, который вызывает версию MoveHere для HRESULT, то этот объект, скорее всего, проверяет результат и выдает исключение или возвращает IAdsContainer, для которого он создан. Но я понятия не имею, какой объект может быть в середине, и ни код платформы.NET, ни файл.tlb не дают мне никаких подсказок. Любые исключения, которые он создает, не задокументированы.
1 ответ
Он принимает этот последний параметр [out, retval] IDispatch** ppObject
и сделать это возвращаемое значение, и интерпретировать возвращенный HRESULT и бросить COMException
если нужно. Я просто не видел тот реальный код, который делает это.
Я подозреваю, что это [ComImport]
атрибут, который говорит.NET, чтобы относиться к нему по-другому.
На самом деле, исходный код показывает, что есть какой-то особый подход из-за этого атрибута, хотя я не буду притворяться, что полностью понимаю, что происходит.
Например, возьмите GetCustomMarshaledCOMObject
метод. Это вызывает GetIUnknown
и делает какую-то особую магию, когда это возвращается false
,
GetIUnknown
метод специально проверяет ComImportAttribute
и возвращается false
если это там.
Даже метод, который вызывает GetCustomMarshaledCOMObject
говорит:
// Check for COMObject & do some special custom marshaling