使用 IDirectoryObject 接口访问属性

IDirectoryObject 接口为使用 C 和 C++ 编写的客户端应用程序提供对目录服务对象的直接访问。 该接口通过直接网络协议(而不是通过 ADSI 属性缓存)实现访问。 代替 IADs 接口支持的属性,IDirectoryObject 提供了支持对象维护方法的关键子集的方法,并提供对其属性的访问权限。 使用 IDirectoryObject,客户端可以使用一个方法调用来获取或设置任意数量的对象属性。 与批处理的相应自动化方法不同,在调用 IDirectoryObject 时执行这些方法。 由于此接口上的方法不需要创建自动化目录对象的实例,因此性能开销很小。

用 C 和 C++ 等语言编写的客户端应使用 IDirectoryObject 接口的方法来优化性能并利用本机目录服务接口。 自动化客户端无法使用 IDirectoryObject。 相反,它们应使用 IADs 接口。

IDirectoryObject::GetObjectAttributes 方法检索具有单个值和多个值的属性。 此方法采用请求的属性列表并返回 ADS_ATTR_INFO 结构。 ADSI 分配此结构;当不再需要使用 FreeADsMem 函数时,调用方必须释放此内存。

返回属性值的顺序不一定与请求属性的顺序相同。 因此,有必要比较从 ADSI 返回的属性名称。

注意

ADS_ATTR_INFO结构不返回请求的所有属性。 只有包含值的那些属性是返回结构的一部分。

 

返回的属性数由传递给 IDirectoryObject::GetObjectAttributes 方法的 dwNumberAttributes 参数确定。

下面的代码示例绑定到对象,并使用 IDirectoryObject::GetObjectAttributes 方法检索对象的属性。

HRESULT hr;
IDirectoryObject *pDirObject;

CoInitialize(NULL);

hr = ADsGetObject(
       L"LDAP://CN=Jeff Smith,OU=Users,DC=Fabrikam,DC=com",
       IID_IDirectoryObject, 
       (void**)&pDirObject);

if(SUCCEEDED(hr))
{
  ADS_ATTR_INFO *pAttrInfo = NULL;
  LPWSTR pAttrNames[] = {L"cn", L"title", L"otherTelephone"};
  DWORD dwNumAttr = sizeof(pAttrNames)/sizeof(LPWSTR);
  DWORD dwReturn;

  //////////////////////////////////////////////////
  // Get attribute values requested.
  // Be aware that the order is not necessarily the 
  // same as requested using pAttrNames.
  //////////////////////////////////////////////////
  hr = pDirObject->GetObjectAttributes(pAttrNames, 
                                       dwNumAttr, 
                                       &pAttrInfo, 
                                       &dwReturn);
     
  if(SUCCEEDED(hr))
  {
    for(DWORD idx = 0; idx < dwReturn; idx++)
      {
        if(_wcsicmp(pAttrInfo[idx].pszAttrName, L"cn") == 0)
        {
          if(pAttrInfo[idx].dwADsType == ADSTYPE_CASE_IGNORE_STRING)
          {
            wprintf(L"Common Name: %s\n", 
                    pAttrInfo[idx].pADsValues[0].CaseIgnoreString);
          }
        }
        else if(_wcsicmp(pAttrInfo[idx].pszAttrName, L"title") == 0)
        {
          if(pAttrInfo->dwADsType == ADSTYPE_CASE_IGNORE_STRING)
          {
            wprintf(L"Title: %s\n", 
                    pAttrInfo[idx].pADsValues[0].CaseIgnoreString);
          }
        }
        else if(_wcsicmp(pAttrInfo[idx].pszAttrName, 
                L"otherTelephone") == 0)
        {  
          // Print the multi-valued property, "Other Telephones".
          if(pAttrInfo[idx].dwADsType == ADSTYPE_CASE_IGNORE_STRING)
        {
          wprintf(L"Other Telephones:");
          for(DWORD val = 0; val < pAttrInfo[idx].dwNumValues; val++) 
          {
            wprintf(L"  %s\n", 
                    pAttrInfo[idx].pADsValues[val].CaseIgnoreString);
          }
        }
      }
    }

    FreeADsMem(pAttrInfo);
  }
     
  pDirObject->Release();
}

CoUninitialize();