首页 > 解决方案 > 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,并通过 out 参数给调用者一个指向该对象的指针。但是 .NET 包装器具有不同的签名,并且没有 HRESULT。

两个问题:

  1. UnsafeNativeMethods.IAdsContainer.MoveHere 如何映射到具有不同签名的 COM 接口?
  2. HRESULT 发生了什么?

关于 #2... 如果中间有一个对象调用 MoveHere 的 HRESULT 版本,则该对象可能会检查结果并引发异常或返回它实例化的 IAdsContainer。但我不知道中间可能是什么对象,.NET 框架代码和 .tlb 文件都没有给我任何线索。它抛出的任何异常都没有记录。

标签: c#active-directorypinvokecomexceptiondirectoryentry

解决方案


它采用最后一个参数[out, retval] IDispatch** ppObject并将其作为返回值,并解释返回的 HRESULT 并COMException在需要时抛出一个。我只是还没有看到执行此操作的实际代码。

我怀疑正是这个[ComImport]属性告诉.NET 以不同的方式对待它。

事实上,源代码确实显示了由于该属性而进行的一些特殊处理,尽管我不会假装我完全理解发生了什么。

例如,采取GetCustomMarshaledCOMObject方法。当它返回时,它会调用GetIUnknown并执行一些特殊的魔法false

GetIUnknown方法专门检查ComImportAttribute并返回false是否存在。

甚至调用的方法也GetCustomMarshaledCOMObject说:

// Check for COMObject & do some special custom marshaling

推荐阅读