DirectoryEntry.MoveTo 异常:由 UnsafeNativeMethods 抽象但未记录
DirectoryEntry.MoveTo exceptions: Abstracted by UnsafeNativeMethods but not documented
System.DirectoryServices 包含 class/method DirectoryEntry.MoveTo(..)
。如果目标 DirectoryEntry 不是容器,唯一记录的异常是 InvalidOperationException
。我预计会有各种其他潜在的例外情况,尤其是在权限方面。
在后台,.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 returns一个HRESULT,并通过一个out参数给调用者一个指向对象的指针。但是 .NET 包装器具有不同的签名,并且没有 HRESULT。
两个问题:
- 如何 UnsafeNativeMethods.IAdsContainer.MoveHere 映射到具有不同签名的 COM 接口?
- 那个 HRESULT 发生了什么?
关于#2...如果中间有一个对象调用 MoveHere 的 HRESULT 版本,该对象可能会检查结果并抛出异常或返回它实例化的 IAdsContainer。但我不知道中间可能是什么对象,.NET 框架代码和 .tlb 文件都没有给我任何线索。它抛出的任何异常都没有记录。
它采用最后一个参数 [out, retval] IDispatch** ppObject
并将其设为 return 值,并解释 returned HRESULT 并在需要时抛出 COMException
。我只是还没有看到执行此操作的实际代码。
我怀疑是 [ComImport]
属性告诉 .NET 以不同方式对待它。
事实上,源代码确实显示了由于该属性而进行的一些特殊处理,尽管我不会假装我完全理解发生了什么。
例如,使用 GetCustomMarshaledCOMObject
method. It calls GetIUnknown
并在 return 时执行一些特殊的魔法 false
。
GetIUnknown
方法专门检查 ComImportAttribute
和 returns false
是否存在。
甚至 the method that calls GetCustomMarshaledCOMObject
说:
// Check for COMObject & do some special custom marshaling
System.DirectoryServices 包含 class/method DirectoryEntry.MoveTo(..)
。如果目标 DirectoryEntry 不是容器,唯一记录的异常是 InvalidOperationException
。我预计会有各种其他潜在的例外情况,尤其是在权限方面。
在后台,.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 returns一个HRESULT,并通过一个out参数给调用者一个指向对象的指针。但是 .NET 包装器具有不同的签名,并且没有 HRESULT。
两个问题:
- 如何 UnsafeNativeMethods.IAdsContainer.MoveHere 映射到具有不同签名的 COM 接口?
- 那个 HRESULT 发生了什么?
关于#2...如果中间有一个对象调用 MoveHere 的 HRESULT 版本,该对象可能会检查结果并抛出异常或返回它实例化的 IAdsContainer。但我不知道中间可能是什么对象,.NET 框架代码和 .tlb 文件都没有给我任何线索。它抛出的任何异常都没有记录。
它采用最后一个参数 [out, retval] IDispatch** ppObject
并将其设为 return 值,并解释 returned HRESULT 并在需要时抛出 COMException
。我只是还没有看到执行此操作的实际代码。
我怀疑是 [ComImport]
属性告诉 .NET 以不同方式对待它。
事实上,源代码确实显示了由于该属性而进行的一些特殊处理,尽管我不会假装我完全理解发生了什么。
例如,使用 GetCustomMarshaledCOMObject
method. It calls GetIUnknown
并在 return 时执行一些特殊的魔法 false
。
GetIUnknown
方法专门检查 ComImportAttribute
和 returns false
是否存在。
甚至 the method that calls GetCustomMarshaledCOMObject
说:
// Check for COMObject & do some special custom marshaling