Win32 API 日本語リファレンス
ホームNetworking.ActiveDirectory › IADs

IADs

COMIDispatch (デュアル)
IDispatch を実装(デュアルインターフェース)。HSP では comobj 経由でメソッド名による遅延バインド呼び出しができます(vtableインデックス不要)。
IIDfd8256d0-fd15-11ce-abc4-02608c9e7553継承元IDispatch呼び出し名前(IDispatch) または vtbl自前メソッド開始 vtbl7

公式ドキュメント

IADs インターフェイスは、任意の ADSI オブジェクトが持つ基本的なオブジェクト機能、すなわちプロパティとメソッドを定義します。

メソッド 13

vtbl = vtable インデックス(0始まり)。IDispatch 実装のため HSP ではメソッド名でも呼べます(上記)。低レベルの index 呼び出し用に vtbl も掲載。0〜2 は IUnknown。

vtbl 7 HRESULT get_Name(LPWSTR* retval)
retvalLPWSTR*outオブジェクトの相対名を示す文字列を受け取る出力ポインタ。
vtbl 8 HRESULT get_Class(LPWSTR* retval)
retvalLPWSTR*outオブジェクトのスキーマクラス名を示す文字列を受け取る出力ポインタ。
vtbl 9 HRESULT get_GUID(LPWSTR* retval)
retvalLPWSTR*outオブジェクトのGUIDを文字列形式で受け取る出力ポインタ。
vtbl 10 HRESULT get_ADsPath(LPWSTR* retval)
retvalLPWSTR*outオブジェクトのADsパス(バインド用文字列)を受け取る出力ポインタ。
vtbl 11 HRESULT get_Parent(LPWSTR* retval)
retvalLPWSTR*out親コンテナのADsパスを示す文字列を受け取る出力ポインタ。
vtbl 12 HRESULT get_Schema(LPWSTR* retval)
retvalLPWSTR*outオブジェクトのスキーマ定義のADsパスを受け取る出力ポインタ。
vtbl 13 HRESULT GetInfo()

この ADSI オブジェクトがサポートするプロパティの値を、基盤となるディレクトリストアからプロパティキャッシュに読み込みます。

戻り値

このメソッドは、標準の戻り値に加えて、以下の値をサポートします。

詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

IADs::GetInfo 関数は、プロパティキャッシュを初期化または更新するために呼び出されます。これは、基盤となるディレクトリストアからサポートされるプロパティの値を取得することに相当します。

プロパティキャッシュは、初期化されていない状態でも必ずしも空とは限りません。サポートされる任意のプロパティについて IADs::Put または IADs::PutEx を呼び出してプロパティキャッシュに値を設定しても、キャッシュは初期化されていないままです。

IADs::GetInfo を明示的に呼び出すと、キャッシュされているすべてのプロパティ値を上書きして、プロパティキャッシュ全体が読み込みまたは再読み込みされます。一方、暗黙的な呼び出しでは、キャッシュに設定されていないプロパティのみが読み込まれます。ADSI オブジェクトの最新のプロパティ値を取得するには、常に IADs::GetInfo を明示的に呼び出してください。

IADs::GetInfo の明示的な呼び出しはプロパティキャッシュ内のすべての値を上書きするため、IADs::GetInfo の前に IADs::SetInfo を呼び出していないと、キャッシュに加えた変更はすべて失われます。

ADSI コンテナーオブジェクトの場合、IADs::GetInfo はコンテナー自身のプロパティ値のみをキャッシュし、子オブジェクトのプロパティ値はキャッシュしません。

IADs::Get メソッドと IADs::GetInfo メソッドの違いを強調しておくことが重要です。前者はプロパティキャッシュから指定したプロパティの値を返すのに対し、後者は基盤となるディレクトリストアからサポートされるすべてのプロパティ値をプロパティキャッシュに読み込みます。

次のコード例は、IADs::Get メソッドと IADs::GetInfo メソッドの違いを示しています。

Set x = GetObject("LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=com")
                                     ' The first IADs::Get calls
                                     ' GetInfo implicitly.
Debug.Print x.Get("homePhone")       ' Assume value is '999-9999'. 
x.Put "homePhone", "868-4449"        ' Put with no commit(SetInfo)
Debug.Print x.Get("homePhone")       ' Value='868-4449' from the cache.
x.GetInfo                            ' Refresh the cache, get the data 
                                     ' from the directory.
Debug.Print x.Get("homePhone")       ' Value will be '999-9999'.

パフォーマンスを向上させるには、IADs::GetInfoEx を明示的に呼び出して特定のプロパティを更新します。また、オブジェクトの操作用プロパティ値にアクセスする必要がある場合は、IADs::GetInfo ではなく IADs::GetInfoEx を呼び出す必要があります。この関数は、指定したプロパティについて以前にキャッシュされていた値をすべて上書きします。

次のコード例では、WinNT プロバイダーが提供するコンピューターオブジェクトを使用します。サポートされるプロパティには、Owner ("Owner")、OperatingSystem ("Windows NT")、OperatingSystemVersion ("4.0")、Division ("Fabrikam")、ProcessorCount ("Uniprococessor Free")、Processor ("x86 Family 6 Model 5 Stepping 1") があります。既定値はかっこ内に示しています。

Dim pList As IADsPropertyList
Dim pEntry As IADsPropertyEntry
Dim pValue As IADsPropertyValue

On Error GoTo Cleanup
 
Set pList = GetObject("WinNT://localhost,computer")
 
' pList now represents an uninitialized empty property cache.
pList.Put "Owner", "JeffSmith"  ' Property cache remains uninitialized,
                               ' but with one property value.
count = pList.PropertyCount  ' count = 1.
MsgBox "Number of property found in the property cache: " & count
 
v = pList.Get("Division")   ' pList.GetInfo is called implicitly
ShowPropertyCache           ' This will display "JeffSmith" for Owner,
                            ' "Fabrikam" for Division, "Windows NT" for
                            ' OperatingSystem, and so on.
 
pList.GetInfo                ' Refreshes the entire cache, overwriting 
                             ' "JeffSmith" for the Owner property.
ShowPropertyCache            ' This will display "Owner" for Owner,
                             ' "Fabrikam" for Division, "Windows NT" for
                             ' OperatingSystem, and so on.

Cleanup:
    If (Err.Number<>0) Then
        MsgBox("An error has occurred. " & Err.Number)
    End If
    Set pList = Nothing
    Set pEntry = Nothing
    Set pValue = Nothing

 
Private Sub ShowPropertyCache()
    For I = 0 To pList.PropertyCount-1
       Set pEntry = pList.Item(I)
       Debug.Print pEntry.Name
       For Each v In pEntry.Values
           Set pValue = v
           Debug.Print "   " & pvalue.CaseIgnoreString
       Next
    Next
End Sub

次のコード例は、IADs::GetInfo メソッドの効果を示すクライアント側スクリプトです。サポートされるプロパティには、Owner ("Owner")、OperatingSystem ("Windows NT")、OperatingSystemVersion ("4.0")、Division ("Fabrikam")、ProcessorCount ("Uniprococessor Free")、Processor ("x86 Family 6 Model 5 Stepping 1") があります。既定値はかっこ内に示しています。

<html>
<body>
 <table>
    <tr>
       <td>Owner:</td>
       <td><input type=text name=txtOwner></td>
    </tr>
    <tr>
       <td>Operating System:</td>
       <td><input type=text name=txtOS></td>
    </tr>
    <tr>
       <td>Operating System Version:</td>
       <td><input type=text name=txtOSV></td>
    </tr>
    <tr>
       <td>Division:</td>
       <td><input type=text name=txtDiv></td>
    </tr>
 </table>

 <input type=button onClick = "showGetInfo()">
</body>

<script language="vbscript">
Dim pList 

sub showGetInfo()
  Set oFac = CreateObject("ADsFactory")
  path = "WinNT://Fabrikam"
  ADS_SECURE_AUTH = 1
  On Error Resume Next

' Browser security requires enabled/Prompt for "Initialize and 
' script ActiveX Controls not marked as safe"
  Set pList=oFac.OpenDSObject(path,vbNullString,vbNullString,ADS_SECURE_AUTH)
   
  ' pList now represents an uninitialized empty property cache
  pList.Put "Owner" "JeffSmith"  ' Property cache remain uninitialized
                                 ' but with one property value.
   
  v = pList.Get("Division")   ' pList.GetInfo is called implicitly
  ShowPropertyCache           ' This will display "JeffSmith" for Owner,
                              ' "Fabrikam" for Division, "Windows NT"
                              ' for OperatingSystem, and so on.
 
  pList.GetInfo                ' Refreshes entire cache, overwriting 
                               ' "JeffSmith" for the Owner property.
  ShowPropertyCache            ' This will display "Owner" for Owner,
                               ' "Fabrikam" for Division, "Windows NT"
                               ' for OperatingSystem, and so on.
end sub

sub ShowPropertyCache()
  txtOwner.value = pList.Get("Owner")
  txtDiv.value = pList.Get("Division")
  txtOS.Value = pList.Get("OperatingSystem")
  txtOSV.value = pList.Get("OperatingSystemVersion")
end sub
</script>

</html>

次のコード例は、Get と GetInfo の効果を示しています。簡潔にするため、エラーチェックは省略しています。

IADs *pADs;
IADsPropertyList *pList;
BSTR bstr;
VARIANT var;
HRESULT hr;
 
hr = ADsGetObject(L"WinNT://somecomputer,computer",
                  IID_IADsPropertyList,
                  (void**)&pList);

if(!(hr==S_OK)){return hr;}

VariantInit(&var);
 
// Get the number of property entries, should be zero.
long pCount;      
hr = pList->get_PropertyCount(&pCount);
printf("    prop count = %d\n",pCount);     // 0 for empty cache.
 
hr = pList->QueryInterface(IID_IADs, (void**)&pADs);
 
 
// Set "Owner=JeffSmith" in the property cache.
V_BSTR(&var) = SysAllocString(L"JeffSmith");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("Owner"), var);
VariantClear(&var);
 
// This time the number of property entries should read one (1).
hr = pList->get_PropertyCount(&pCount);
printf("    prop count = %d\n",pCount);    // 1 for what was set.
 
// The following Get invokes GetInfo implicitly, but 
// the cache (that is, "Owner=JeffSmith") remains intact.
hr = pADs->Get(CComBSTR("Division"), &var);  
printf("    division   = %S\n", V_BSTR(&var));
VariantClear(&var);
 
hr = pADs->Get(CComBSTR("Owner"), &var);
printf("    owner      = %S\n", V_BSTR(&var));  // Owner = JeffSmith
VariantClear(&var);
 
// The following GetInfo call refreshes the entire prop cache.
// Now Owner is no longer "JeffSmith", but the value stored in the
// persistent store, for example, "BenSmith".
hr = pADs->GetInfo();
 
hr = pADs->Get(CComBSTR("Owner"), &var);
printf("    owner      = %S\n", V_BSTR(&var));  // Owner = BenSmith
VariantClear(&var);
 
// ...

if(pADs)
   pADs->Release();

if(pList)
   pList->Release();
vtbl 14 HRESULT SetInfo()

IADs::SetInfo メソッドは、ADSI オブジェクトのキャッシュされたプロパティ値を、基盤となるディレクトリストアに保存します。

戻り値

このメソッドは、処理が成功した場合の S_OK を含む標準の戻り値をサポートします。詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

IADs::Put メソッドと IADs::SetInfo メソッドの違いを強調しておくことが重要です。前者はプロパティキャッシュ内の指定したプロパティの値を設定 (または変更) するのに対し、後者はプロパティキャッシュの変更を基盤となるディレクトリストアに反映します。したがって、IADs::SetInfo を呼び出す前に IADs::GetInfo (または IADs::GetInfoEx) を呼び出すと、IADs::Put で行ったプロパティ値の変更はすべて失われます。

IADs::SetInfo はネットワークを介してデータを送信するため、このメソッドの使用は最小限にとどめてください。これにより、クライアントがサーバーへアクセスする回数を減らせます。たとえば、キャッシュから永続ストアへのプロパティ変更は、すべて、または大部分を 1 回のバッチでコミットするようにします。

このガイドラインは、IADs::SetInfoIADs::Put メソッドとの関係にのみ当てはまり、IADs::PutEx メソッドとの関係とは異なります。

次のコード例は、IADs::PutIADs::SetInfo の推奨される関係を示しています。

Dim obj as IADs
 
obj.Put(prop1,val1)
obj.Put(prop2.val2)
obj.Put(prop3.val3)
obj.SetInfo

次のコード例は、IADs::PutIADs::SetInfo の間で推奨されない使い方を示しています。

obj.Put(prop1,val1)
obj.SetInfo
obj.Put(prop2.val2)
obj.SetInfo
obj.Put(prop3.val3)
obj.SetInfo

IADs::PutEx と組み合わせて使用する場合、IADs::SetInfo は、ADS_PROPERTY_UPDATEADS_PROPERTY_CLEAR などの制御コードで指定された操作要求を、基盤となるディレクトリストアに渡します。

次の Visual Basic のコード例は、IADs::SetInfo メソッドを使用して、ユーザーのプロパティ値を基盤となるディレクトリに保存します。

Dim x as IADs
On Error GoTo Cleanup

Set x = GetObject("LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=com")
'
' Update values in the cache.
'
x.Put "sn", "Smith"
x.Put "givenName", "Jeff"
x.Put "street", "1 Tanka Place"
x.Put "l", "Sammamish"
x.Put "st", "Washington"
'
' Commit changes to the directory.
x.SetInfo

Cleanup:
   If (Err.Number<>0) Then
      MsgBox("An error has occurred. " & Err.Number)
   End If
   Set x = Nothing

次の C++ のコード例は、プロパティキャッシュ内のプロパティ値を更新し、IADs::SetInfo を使用してその変更をディレクトリストアにコミットします。簡潔にするため、エラーチェックは省略しています。

IADs *pAds NULL;
VARIANT var;
HRESULT hr = S_OK;
LPWSTR path=L"LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=com";
hr = ADsGetObject( path, IID_IADs, (void**) pADs);

if(!(hr==S_OK)) {return hr;}

VariantInit(&var);
// Update values in the cache.
V_BSTR(&var) = SysAllocString(L"Smith");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("sn"), var );
VariantClear(&var);
 
V_BSTR(&var) = SysAllocString(L"Jeff");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("givenName"), var );
VariantClear(&var);
 
V_BSTR(&var) = SysAllocString(L"1 Tanka Place");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("street"), var );
VariantClear(&var);
 
V_BSTR(&var) = SysAllocString(L"Sammamish");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("l"), var );
VariantClear(&var);
 
V_BSTR(&var) = SysAllocString(L"Washington");
V_VT(&var) = VT_BSTR;
hr = pADs->Put(CComBSTR("st"), var );
VariantClear(&var);
 
// Commit changes to the directory store.
hr = pADs->SetInfo();

if(pADs)
   pADs->Release();
vtbl 15 HRESULT Get(LPWSTR bstrName, VARIANT* pvProp)

指定した名前のプロパティをプロパティキャッシュから取得します。

bstrNameLPWSTRinプロパティ名を指定する BSTR を格納します。
pvPropVARIANT*outプロパティの値を受け取る VARIANT へのポインターです。多値プロパティの場合、プロパティがバイナリ型でない限り、pvPropVARIANT のバリアント配列になります。バイナリ型の場合、pvProp はバイトのバリアント配列 (VT_U1 または VT_ARRAY) になります。オブジェクトを参照するプロパティの場合、pvProp は参照先のオブジェクトへの VT_DISPATCH ポインターになります。

戻り値

このメソッドは、標準の戻り値に加えて、以下の値をサポートします。

詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

IADs::Get メソッドでは、呼び出し側が単一値プロパティと多値プロパティの値を別々に扱う必要があります。したがって、対象のプロパティが単一値か多値のどちらであるかが分かっている場合は、IADs::Get メソッドを使用してプロパティ値を取得します。次のコード例は、このメソッドを呼び出す際に、呼び出し側が単一値プロパティと多値プロパティをどのように扱えるかを示しています。

プロパティが初期化されていない場合、このメソッドを呼び出すと IADs::GetInfo メソッドが暗黙的に呼び出されます。これにより、キャッシュに設定されていないサポート対象プロパティの値が、基盤となるディレクトリストアから読み込まれます。以降の IADs::Get の呼び出しは、キャッシュ内のプロパティ値のみを対象とします。IADs::GetInfo の暗黙的な呼び出しと明示的な呼び出しの動作の詳細については、IADs::GetInfo を参照してください。

プロパティキャッシュからプロパティ値を取得するには、IADs::GetEx を使用することもできます。ただし、その場合は単一値か多値かにかかわらず、値は VARIANT のバリアント配列として返されます。つまり、ADSI は返すプロパティ値を一貫したデータ形式にまとめようとします。これにより、返されたデータが単一値か複数値か分からない場合でも、呼び出し側はデータ型を検証する手間を省けます。

次のコード例は、IADs::Get を使用してオブジェクトのセキュリティ記述子を取得します。

Dim x As IADs
Dim Desc As IADsSecurityDescriptor
On Error GoTo ErrTest:
 
Set x = GetObject("LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=com")
 
' Single-valued properties.
Debug.Print "Home Phone Number is: " & x.Get("homePhone")
 
' Some property values represents other ADSI objects. 
' Consult your provider documentation.
Set Desc = x.Get("ntSecurityDescriptor")
 
' Multi-valued property, assuming that multiple values were
' assigned to the "otherHomePhone" properties. Caller must 
' enumerate all the available values.
Debug.Print "Other Phone Numbers are: "
otherNumbers = x.Get("otherHomePhone")
For Each homeNum In otherNumbers
  Debug.Print homeNum
Next
 
Exit Sub
 
ErrTest:
  Debug.Print Hex(Err.Number)
  Set x = Nothing
  Set Desc = Nothing

次のコード例は、IADs::GetIADs::Put を使用して、バイナリデータのプロパティ値を扱う方法を示しています。

Dim oTarget As IADs
Dim Octet(5) As Byte
Dim MultiOctet(2) As Variant
Dim i As Integer, j As Integer

On Error GoTo Cleanup
 
' Set up MultiOctetString.
For i = 0 To 2
    For j = 0 To 5
        Octet(j) = CByte(i * j)
    Next j
    MultiOctet(i) = Octet
Next i
 
' Bind to the object and set MultiOctetString.
Set oTarget=GetObject("LDAP://CN=SomeUser,CN=Users,DC=Fabrikam, DC=COM")
oTarget.Put "multiOctetString", MultiOctet
oTarget.SetInfo
 
Dim GetOctet As Variant
Dim Temp As Variant
 
' Read back and print MultiOctetString.
GetOctet = oTarget.Get("multiOctetString")
For i = LBound(GetOctet) To UBound(GetOctet)
    Temp = GetOctet(i)
    For j = LBound(Temp) To UBound(Temp)
        Debug.Print Temp(j)
    Next j
    Debug.Print "----"
Next i

Exit Sub

Cleanup:
   MsgBox("An error has occurred. " & Err.Number)
   Set oTarget = Nothing

次のコード例は、IADs::Get を使用して、オブジェクトの省略可能なプロパティの値を取得する方法を示しています。

<HTML>
<head><title></title></head>

<body>
<%
Dim x 
 
On error resume next
Set x = GetObject("WinNT://Fabrikam/Administrator")
Response.Write "Object Name: " & x.Name & "<br>"
Response.Write "Object Class: " & x.Class & "<br>"
 
' Get optional property values of this object.
Set cls = GetObject(x.Schema)

For Each op In cls.OptionalProperties
   v = obj.Get(op)
   if err.Number = 0 then
       Response.Write "Optional Property: " & op & "=" & v & "<br>"
   end if
Next
%>

</body>
</html>

次のコード例は、IADs::Get を使用して、単一値および複数値の属性を読み取ります。

HRESULT hr;
IADs *pUsr=NULL;
 
CoInitialize(NULL);
 
///////////////////////////////
// Bind to a directory object.
///////////////////////////////
hr = ADsGetObject(L"WinNT://Fabrikam/Administrator,user", IID_IADs, (void**) &pUsr );
if ( !SUCCEEDED(hr) ) { return hr; }
 
//////////////////////////////////
// Get a single-valued attribute.
//////////////////////////////////
VARIANT var;
VariantInit(&var);
 
hr = pUsr->Get(CComBSTR("FullName"), &var );
if ( SUCCEEDED(hr) )
{
    printf("FullName: %S\n", V_BSTR(&var) );
    VariantClear(&var);
}
 
if ( pUsr )
{
    pUsr->Release();
}
 
///////////////////////////////////////////////////////
// Get a multi-valued attribute from a service object.
///////////////////////////////////////////////////////
IADs *pSvc = NULL;
 
hr = ADsGetObject(L"WinNT://Fabrikam/Account/Browser,service", IID_IADs, (void**) &pSvc );
if ( !SUCCEEDED(hr) )
{
    return hr;
}
 
hr = pSvc->Get(CComBSTR("Dependencies"), &var );
if ( SUCCEEDED(hr) )
{
    LONG lstart, lend;
    SAFEARRAY *sa = V_ARRAY( &var );
    VARIANT varItem;
 
    // Get the lower and upper bound.
    hr = SafeArrayGetLBound( sa, 1, &lstart );
    hr = SafeArrayGetUBound( sa, 1, &lend );
 
    // Iterate and print the content.
    VariantInit(&varItem);
    printf("Getting service dependencies using IADs :\n");
    for ( long idx=lstart; idx <= lend; idx++ )
    {
        hr = SafeArrayGetElement( sa, &idx, &varItem );
        printf("%S ", V_BSTR(&varItem));
        VariantClear(&varItem);
    }
    printf("\n");
 
    VariantClear(&var);
}
 
// Cleanup.
if ( pSvc )
{
    pSvc->Release();
}
vtbl 16 HRESULT Put(LPWSTR bstrName, VARIANT vProp)

ADSI 属性キャッシュ内の属性の値を設定します。

bstrNameLPWSTRinプロパティ名を指定する BSTR を格納します。
vPropVARIANTinプロパティの新しい値を指定する VARIANT を格納します。

戻り値

このメソッドは、標準の戻り値に加えて、以下の値をサポートします。

詳細情報およびその他の戻り値については、ADSI Error Codes を参照してください。

解説(Remarks)

Put による新しいプロパティ値の割り当ては、プロパティキャッシュ内でのみ行われます。変更をディレクトリストアに反映するには、Put を呼び出した後に、そのオブジェクトに対して IADs::SetInfo を呼び出します。

単純な割り当て以外の方法でプロパティ値を操作するには、Put を使用して、既存の属性値の配列に値を追加したり、そこから値を削除したりします。

次のコード例は、IADs::Put メソッドの使用方法を示しています。

Dim x As IADs
On Error GoTo Cleanup

Set x = GetObject("LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam, DC=Com") 
x.Put "givenName", "Jeff"
x.Put "sn", "Smith"
x.SetInfo    ' Commit to the directory.

Cleanup:
   If(Err.Number<>0) Then
      MsgBox("An error has occurred. " & Err.Number)
   End If
   Set x = Nothing

次のコード例は、IADs::Put メソッドの使用方法を示しています。

HRESULT hr;
IADs *pADs = NULL;
LPWSTR pszADsPath = L"LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com";
 
CoInitialize(NULL);
 
//////////////////////////////////
// Modifying attributes using IADs
//////////////////////////////////
hr = ADsGetObject(pszADsPath, IID_IADs, (void**) &pADs);
 
if(SUCCEEDED(hr))
{ 
    VARIANT var;
    VariantInit(&var);
     
    // Set the first name.
    V_BSTR(&var) = SysAllocString(L"Jeff");
    V_VT(&var) = VT_BSTR;
    hr = pADs->Put(CComBSTR("givenName"), var);
     
    // Set the last name.
    VariantClear(&var);
    V_BSTR(&var) = SysAllocString(L"Smith");
    V_VT(&var) = VT_BSTR;
    hr = pADs->Put(CComBSTR("sn"), var); 
    VariantClear(&var);

    // Other Telephones.
    LPWSTR pszPhones[] = { L"425-707-9790", L"425-707-9791" };
    DWORD dwNumber = sizeof(pszPhones)/sizeof(LPWSTR);
    hr = ADsBuildVarArrayStr(pszPhones, dwNumber, &var);
    hr = pADs->Put(CComBSTR("otherTelephone"), var); 
    VariantClear(&var);
     
    // Commit the change to the directory.
    hr = pADs->SetInfo();
    pADs->Release();
}

CoUninitialize();
vtbl 17 HRESULT GetEx(LPWSTR bstrName, VARIANT* pvProp)

指定した属性のプロパティ値を、プロパティキャッシュから取得します。

bstrNameLPWSTRinプロパティ名を指定する BSTR を格納します。
pvPropVARIANT*outプロパティの値 (単数または複数) を受け取る VARIANT へのポインターです。

戻り値

このメソッドは、標準の戻り値に加えて、以下の一覧に示す戻り値をサポートします。

詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

IADs::Get メソッドと IADs::GetEx メソッドは、単一値プロパティの値に対して異なるバリアント構造を返します。プロパティが文字列の場合、IADs::Get は文字列のバリアント (VT_BSTR) を返すのに対し、IADs::GetEx は要素が 1 つの VARIANT 型文字列のバリアント配列を返します。したがって、多値属性が単一の値を返すか複数の値を返すか分からない場合は、IADs::GetEx を使用してください。IADs::GetEx は結果のデータ構造を検証する必要がないため、単一値か複数値か分からない状態でプロパティを取得する場合に使用するとよいでしょう。次の一覧は、この 2 つのメソッドを比較したものです。

IADs::Get 版 IADs::GetEx 版
Dim x as IADs

otherNumbers = x.Get("otherHomePhone")
If VarType(otherNumbers) = vbString Then
  Debug.Print otherNumbers
Else
  For Each homeNum In otherNumbers
    Debug.Print homeNum
  Next
End If
Dim x as IADs

otherNumbers = x.GetEx("otherHomePhone")
For Each homeNum In otherNumbers
  Debug.Print homeNum
Next

IADs::Get メソッドと同様に、IADs::GetEx は初期化されていないプロパティキャッシュに対して IADs::GetInfo を暗黙的に呼び出します。IADs::GetInfo の暗黙的な呼び出しと明示的な呼び出しの詳細については、IADs::GetInfo を参照してください。

次のコード例は、IADs::GetEx を使用してオブジェクトのプロパティを取得する方法を示しています。

Dim x As IADs
On Error GoTo ErrTest:
 
Set x = GetObject("LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=com")
 
' Single value property.
Debug.Print "Home Phone Number is: " 
phoneNumber = x.GetEx(""homePhone")
For Each homeNum in phoneNumber
    Debug.Print homeNum
Next
 
' Multiple value property.
Debug.Print "Other Phone Numbers are: "
otherNumbers = x.GetEx("otherHomePhone")
For Each homeNum In otherNumbers
    Debug.Print homeNum
Next
Exit Sub
 
ErrTest:
    Debug.Print Hex(Err.Number)
    Set x = Nothing

次のコード例は、IADs::Get メソッドを使用して、オブジェクトの省略可能なプロパティの値を取得する方法を示しています。

<HTML>
<head><title></title></head>

<body>
<%
Dim x 

On Error Resume Next
Set x = GetObject("WinNT://Fabrikam/Administrator")
Response.Write "Object Name: " & x.Name & "<br>"
Response.Write "Object Class: " & x.Class & "<br>"
 
' Get the optional property values for this object.
Set cls = GetObject(x.Schema)
For Each op In cls.OptionalProperties
   vals = obj.GetEx(op)
   if err.Number = 0 then
       Response.Write "Optional Property: & op & "=" 
       for each v in vals 
          Response.Write v & " "
       next
       Response.Write "<br>"
   end if
Next
%>

</body>
</html>

次のコード例は、IADs::GetEx を使用して "homePhone" プロパティの値を取得します。

IADs *pADs = NULL;
 
hr = ADsGetObject(L"LDAP://CN=Administrator,CN=Users,DC=Fabrikam,DC=Com", IID_IADs, (void**) &pADs );
if ( !SUCCEEDED(hr) ) { return hr;}
 
hr = pADs->GetEx(CComBSTR("homePhone"), &var);
if ( SUCCEEDED(hr) )
{
    LONG lstart, lend;
    SAFEARRAY *sa = V_ARRAY( &var );
    VARIANT varItem;
 
    // Get the lower and upper bound.
    hr = SafeArrayGetLBound( sa, 1, &lstart );
    hr = SafeArrayGetUBound( sa, 1, &lend );
 
    // Iterate and print the content.
    VariantInit(&varItem);
    printf("Getting Home Phone using IADs::Get.\n");
    for ( long idx=lstart; idx <= lend; idx++ )
    {
        hr = SafeArrayGetElement( sa, &idx, &varItem );
        printf("%S ", V_BSTR(&varItem));
        VariantClear(&varItem);
    }
    printf("\n");
 
    VariantClear(&var);
}
 
// Cleanup.
if ( pADs )
{
    pADs->Release();
}
vtbl 18 HRESULT PutEx(INT lnControlCode, LPWSTR bstrName, VARIANT vProp)

ADSI 属性キャッシュ内の属性の値を変更します。

lnControlCodeINTin変更のモード (Append、Replace、Remove、Delete) を示す制御コードです。詳細および値の一覧については、ADS_PROPERTY_OPERATION_ENUM を参照してください。
bstrNameLPWSTRinプロパティ名を指定する BSTR を格納します。
vPropVARIANTinプロパティの新しい値 (単数または複数) を格納する VARIANT 配列を格納します。単一値プロパティは、要素が 1 つの配列として表されます。InControlCodeADS_PROPERTY_CLEAR が設定されている場合、vProp で指定するプロパティの値は無視されます。

戻り値

このメソッドは、標準の戻り値に加えて、以下の値をサポートします。

詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

PutEx は通常、多値属性に値を設定するために使用します。IADs::Put メソッドとは異なり、PutEx では、値を変更する前に属性値を取得する必要はありません。ただし、PutEx は ADSI プロパティキャッシュに含まれる属性値のみを変更するため、変更をディレクトリにコミットするには、PutEx の呼び出しごとに IADs::SetInfo を使用する必要があります。

PutEx を使用すると、ADS_PROPERTY_APPEND を指定して、多値属性の既存の値の集合に値を追加できます。多値属性の値を更新、追加、または削除する場合は、配列を使用する必要があります。

Active Directory は、多値属性に対する重複した値を受け付けません。PutEx を呼び出して Active Directory オブジェクトの多値属性に重複した値を追加した場合、PutEx の呼び出しは成功しますが、重複した値は無視されます。

同様に、PutEx を使用して Active Directory オブジェクトの多値プロパティから 1 つ以上の値を削除する場合、指定した値の一部またはすべてがプロパティに設定されていなくても、操作は成功します。つまり、エラーは発生しません。

メモ WinNT プロバイダーは、InControlCode 引数で渡された値を無視し、PutEx の使用時には ADS_PROPERTY_UPDATE 要求と同等の処理を実行します。

次のコード例は、IADs.PutEx メソッドの使用方法を示しています。

Dim x As IADs

On Error GoTo Cleanup

Set x = GetObject("LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com")
'----------------------------------------------------------
' Assume the otherHomePhone has the values
' 425-707-9790, 425-707-9791
'----------------------------------------------------------
 
' Adding a value
x.PutEx ADS_PROPERTY_APPEND, "otherhomePhone", Array("425-707-9792")  
x.SetInfo              ' Now the values are 425-707-9790,425-707-9791,425-707-9792. 
deleting two values
x.PutEx ADS_PROPERTY_DELETE, "otherHomePhone", Array("425-707-9790", "425-707-9791")
x.SetInfo              ' Now the values are 425-707-9792.
 
' Changing the remaining value
x.PutEx ADS_PROPERTY_UPDATE, "otherHomePhone", Array("425-707-9793", "425-707-9794")
x.SetInfo              ' Now the values are 425-707-9793,425-707-9794.
 
' Deleting the value
x.PutEx ADS_PROPERTY_CLEAR, "otherHomePhone",  vbNullString
x.SetInfo              ' Now the property has no value.

Cleanup:
    If(Err.Number<>0) Then
        MsgBox("An error has occurred. " & Err.Number)
    End If
    Set x = Nothing

次のコード例は、IADs::PutEx メソッドの使用方法を示しています。

HRESULT hr;
IADs *pADs=NULL;
LPWSTR pszADsPath = L"LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com";
 
CoInitialize(NULL);
 
hr = ADsGetObject(pszADsPath, IID_IADs, (void**) &pADs);

if(SUCCEEDED(hr)) 
{
    VARIANT var;
    VariantInit(&var);
     
    LPWSTR pszPhones[] = { L"425-707-9790", L"425-707-9791" };
    DWORD dwNumber = sizeof(pszPhones)/sizeof(LPWSTR);
    hr = ADsBuildVarArrayStr(pszPhones, dwNumber, &var);
    hr = pADs->Put(CComBSTR("otherHomePhone"), var); 
    VariantClear(&var);
    hr = pADs->SetInfo();   // The phone list is now 425-707-9790, 425-707-9791.
     
    // Append another number to the list.
    LPWSTR pszAddPhones[]={L"425-707-9792"};
    hr = ADsBuildVarArrayStr(pszAddPhones, 1, &var);
    hr = pADs->PutEx(ADS_PROPERTY_APPEND, CComBSTR("otherHomePhone"), var);
    hr = pADs->SetInfo();   // The list becomes 
                            // 425-707-9790, 425-707-9791, 425-707-9792.
    VariantClear(&var);
     
    hr = ADsBuildVarArrayStr(pszPhones, dwNumber, &var);
    hr = pADs->PutEx(ADS_PROPERTY_DELETE, CComBSTR("otherHomePhone"), var);
    hr = pADs->SetInfo();  // The list becomes 425-707-9792.
     
    pszPhones[0] = L"425-707-9793";
    pszPhones[1] = L"425-707-9794";
    hr = ADsBuildVarArrayStr(pszPhones, dwNumber, &var);
    hr = pADs->PutEx(ADS_PROPERTY_UPDATE, CComBSTR("otherHomePhone"), var);
    hr = pADs->SetInfo();  // The list becomes 425-707-9793, 425-707-9794.
     
    VariantClear(&var);
    V_VT(&var)=VT_NULL;
    hr = pADs->PutEx(ADS_PROPERTY_CLEAR, CComBSTR("otherHomePhone"), var);
    hr = pADs->SetInfo();  // The list is empty.

    VariantClear(&var);
    pADs->Release();
}

hr = CoUninitialize();
vtbl 19 HRESULT GetInfoEx(VARIANT vProperties, INT lnReserved)

IADs::GetInfoEx メソッドは、ADSI オブジェクトの指定したプロパティの値を、基盤となるディレクトリストアからプロパティキャッシュに読み込みます。

vPropertiesVARIANTinActive Directory プロパティキャッシュに読み込むプロパティを列挙した、null で終わる Unicode 文字列エントリの配列です。各プロパティ名は、このオブジェクトのスキーマクラス定義に含まれるいずれかと一致している必要があります。
lnReservedINTin将来の使用のために予約されています。ゼロに設定する必要があります。

戻り値

このメソッドは、標準の戻り値に加えて、以下の値をサポートします。

詳細については、ADSI Error Codes を参照してください。

解説(Remarks)

IADs::GetInfoEx メソッドは、指定したプロパティについて以前にキャッシュされていた値を、ディレクトリストア内の値で上書きします。したがって、IADs::GetInfoEx を呼び出す前に IADs::SetInfo を呼び出していないと、キャッシュに加えた変更はすべて失われます。

ADSI オブジェクトのプロパティキャッシュ内の選択したプロパティの値を更新するには、IADs::GetInfoEx を使用します。すべてのプロパティ値を更新するには、IADs::GetInfo を使用します。

ADSI コンテナーオブジェクトの場合、IADs::GetInfoEx はコンテナー自身のプロパティ値のみをキャッシュし、子オブジェクトのプロパティ値はキャッシュしません。

次のコード例は、目的のプロパティ値がディレクトリ内に存在すると仮定して、IADs::GetInfoEx を使用して選択したプロパティの値を取得する方法を示しています。

Dim x As IADs
On Error GoTo Cleanup

Set x = GetObject("LDAP://CN=JeffSmith,CN=Users,DC=Fabrikam,DC=com")
 
' Retrieve givenName and sn from the underlying directory storage.
' Cache should have givenName and sn values.
x.GetInfoEx Array("givenName", "sn"), 0 
Debug.Print x.Get("givenName")  ' Property is in the cache.
Debug.Print x.Get("sn")         ' Property is in the cache.
 
' If the "homePhone" property is not in the cache (in the next line), 
' GetInfo is called implicitly.
Debug.Print x.Get("homePhone")

Cleanup:
   If(Err.Number<>0) Then
      MsgBox("An error has occurred. " & Err.Number);
   End If

   Set x = Nothing

次のコード例は、目的のプロパティ値がディレクトリ内に存在すると仮定して、IADs::GetInfoEx を使用して選択したプロパティの値を取得する方法を示しています。簡潔にするため、エラーチェックは省略しています。

IADs *pADs = NULL;
VARIANT var;
HRESULT hr = S_OK;
 
hr = ADsGetObject(L"WinNT://somecomputer,computer",
                  IID_IADs,
                  (void**)&pADs);

if(!(hr==S_OK)){return hr;} 

VariantInit(&var);
 
// Get "Owner" and "Division" attribute values.
LPWSTR pszAttrs[] = { L"Owner", L"Division" };
DWORD dwNumber = sizeof( pszAttrs ) /sizeof(LPWSTR);
hr = ADsBuildVarArrayStr( pszAttrs, dwNumber, &var );
hr = pADs->GetInfoEx(var, 0);
VariantClear(&var);
 
hr = pADs->Get(CComBSTR("Division"), &var);  
printf("    division   = %S\n", V_BSTR(&var));
VariantClear(&var);
hr = pADs->Get(CComBSTR("Owner"), &var);
printf("    owner      = %S\n", V_BSTR(&var));
VariantClear(&var);

if(pADs)
   pADs->Release();

出典・ライセンス: 上記「公式ドキュメント」の内容は Microsoft の Win32 API ドキュメント(MicrosoftDocs/sdk-api)を日本語に翻訳・改変したものです。© Microsoft Corporation. CC BY 4.0 で提供。
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)

HSP用 COM定義

#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"

出力引数:
#define global IID_IADs "{FD8256D0-FD15-11CE-ABC4-02608C9E7553}"
#usecom global IADs IID_IADs "{}"
#comfunc global IADs_get_Name     7 var
#comfunc global IADs_get_Class    8 var
#comfunc global IADs_get_GUID     9 var
#comfunc global IADs_get_ADsPath  10 var
#comfunc global IADs_get_Parent   11 var
#comfunc global IADs_get_Schema   12 var
#comfunc global IADs_GetInfo      13
#comfunc global IADs_SetInfo      14
#comfunc global IADs_Get          15 wstr,var
#comfunc global IADs_Put          16 wstr,int
#comfunc global IADs_GetEx        17 wstr,var
#comfunc global IADs_PutEx        18 int,wstr,int
#comfunc global IADs_GetInfoEx    19 int,int
; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。
; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。
; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。
; ※IDispatch 実装。HSP では comobj 経由でメソッド名による呼び出しも可能(vtbl 不要)。