IADsContainer
COMIDispatch (デュアル)comobj 経由でメソッド名による遅延バインド呼び出しができます(vtableインデックス不要)。公式ドキュメント
IADsContainer インターフェイスは、ADSI コンテナー オブジェクトが、格納された ADSI オブジェクトを作成、削除、および管理できるようにします。コンテナー オブジェクトは、ファイル システムのような階層的なディレクトリ ツリーを表し、ディレクトリ階層を編成します。
解説(Remarks)
オブジェクトがコンテナーであるかどうかを判断するには、そのオブジェクトの IADsClass.Container プロパティを使用します。
GUID(または SID)を使用してコンテナー オブジェクトにバインドした場合、そのコンテナー オブジェクトに対しては特定の操作しか実行できません。これらの操作には、オブジェクトの属性の調査と、オブジェクトの直下の子の列挙が含まれます。これらの操作を次のコード例に示します。
Dim con As IADsContainer
Dim obj As IADs
Set con = GetObject("LDAP://svr01/<GUID=xxxx>")
con.Filter = Array("user")
For Each item In con
debug.print item.Name " & " of " & item.Class
Next
その他のすべての操作、つまり GetObject、Create、Delete、CopyHere、MoveHere は、コンテナーの GUID 表現ではサポートされません。たとえば、次のコード例の最後の行はエラーになります。
Dim con As IADsContainer
Dim obj As IADs
Set con = GetObject("LDAP://svr01/<GUID=xxxx>")
Set obj = con.GetObject("user", "CN=Jeff Smith")
GUID(または SID)を使用したバインドは、オーバーヘッドが小さく、そのため高速なバインドを目的としており、多くの場合オブジェクトのイントロスペクションに使用されます。
GUID(または SID)でバインドされたコンテナーのこれらのメソッドを呼び出すには、識別名(DN)を使用してオブジェクトに再バインドしてください。
Dim conGUID, conDN As IADsContainer
Dim obj As IADs
Set conGUID = GetObject("LDAP://svr/<GUID=xxxx>")
Set conDN=GetObject("LDAP://svr/" & conGUID.Get("distinguishedName"))
Set obj = conDN.GetObject("user", "CN=Jeff Smith")
オブジェクトの GUID 表現の詳細については、IADs.GUID を参照してください。
例
次のコード例は、ADSI オブジェクトがコンテナーであるかどうかを判断します。
Dim obj As IADs
Dim cls As IADsClass
On Error GoTo Cleanup
Set obj = GetObject("WinNT://myComputer,computer")
Set cls = GetObject(obj.Schema)
If (cls.Container = TRUE) Then
MsgBox "The object is a container."
Else
MsgBox "The object is a leaf."
End If
Cleanup:
If (Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set obj = Nothing
Set cls = Nothing
次のコード例は、ADSI オブジェクトがコンテナーであるかどうかを判断します。
IADs *pADs = NULL;
IADsClass *pCls = NULL;
HRESULT hr = S_OK;
BSTR bstr;
hr = ADsGetObject(L"WinNT://myComputer,computer", IID_IADs, (void**)&pADs);
if(FAILED(hr)){return;}
pADs->get_Schema(&bstr);
hr = ADsGetObject(bstr, IID_IADsClass, (void**)&pCls);
pADs->Release();
SysFreeString(bstr);
if(FAILED(hr)){return;}
VARIANT_BOOL isContainer;
pCls->get_Container(&isContainer);
if(isContainer)
printf("Object is a container.\n");
else
printf("Object is not a container.\n");
pCls->Release();
メソッド 11
vtbl = vtable インデックス(0始まり)。IDispatch 実装のため HSP ではメソッド名でも呼べます(上記)。低レベルの index 呼び出し用に vtbl も掲載。0〜2 は IUnknown。
| retval | INT* | out | コンテナに含まれる子オブジェクトの数を受け取る出力ポインタ。 |
コンテナーの列挙子オブジェクトを取得します。
| retval | IUnknown** | out | 列挙子オブジェクトを受け取る IUnknown ポインターへのポインター。呼び出し側は、このインターフェイスが不要になったら解放する必要があります。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。エラー コードの詳細については、ADSI Error Codes を参照してください。
解説(Remarks)
関数名には、"get" と "NewEnum" の間に 2 つのアンダースコア文字("__")があります。
Visual Basic では、ForEach… ステートメントを使用して IADsContainer::get__NewEnum メソッドを暗黙的に呼び出します。
C/C++ では、ADsBuildEnumerator、ADsEnumerateNext、AdsFreeEnumerator ヘルパー関数を使用します。
例
次のコード例は、コンテナー内の子オブジェクトを列挙する方法を示します。
Dim cont As IADsContainer
On Error GoTo Cleanup
Set cont = GetObject("LDAP://OU=Sales,DC=Fabrikam,DC=com")
For Each obj In cont
Debug.Print obj.Name
Next
Cleanup:
If(Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set cont = Nothing
次のコード例は、コンテナーに格納されたオブジェクトを列挙する方法を示します。
IEnumVARIANT *pEnum = NULL;
IADsContainer *pCont = NULL;
LPUNKNOWN pUnk = NULL;
VARIANT var;
IDispatch *pDisp = NULL;
ulong lFetch;
IADs *pADs = NULL;
// In this sample, skip error checking.
ADsGetObject(L"LDAP://OU=Sales,DC=Fabrikam,DC=COM",
IID_IADsContainer, (void**) &pCont);
pCont->get__NewEnum(&pUnk);
pCont->Release();
pUnk->QueryInterface(IID_IEnumVARIANT, (void**) &pEnum);
pUnk->Release();
// Enumerate.
HRESULT hr = pEnum->Next(1, &var, &lFetch);
while(SUCCEEDED(hr) && lFetch > 0)
{
if (lFetch == 1)
{
BSTR bstr;
pDisp = V_DISPATCH(&var);
pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pDisp->Release();
hr = pADs->get_Name(&bstr);
if(SUCCEEDED(hr))
{
SysFreeString(bstr);
}
pADs->Release();
}
VariantClear(&var);
hr = pEnum->Next(1, &var, &lFetch);
};
pEnum->Release();
| pVar | VARIANT* | out | 現在の列挙フィルタ(クラス名配列)を保持するVARIANTを受け取る出力ポインタ。 |
| Var | VARIANT | in | 列挙対象を限定するクラス名配列を保持するVARIANT。 |
| pvFilter | VARIANT* | out | プリフェッチ対象の属性名を示すヒント配列のVARIANTを受け取る出力ポインタ。 |
| vHints | VARIANT | in | プリフェッチ対象の属性名を示すヒント配列を保持するVARIANT。 |
コンテナー内のディレクトリ オブジェクトのインターフェイスを取得します。
| ClassName | LPWSTR | in | 取得するオブジェクトのオブジェクト クラスの名前を指定する BSTR。このパラメーターが NULL の場合、プロバイダーはコンテナー内で最初に見つかった項目を返します。 |
| RelativeName | LPWSTR | in | 取得するオブジェクトの相対識別名(相対DN)を指定する BSTR。 |
| ppObject | IDispatch** | out | 指定されたオブジェクト上の IDispatch インターフェイスへのポインターへのポインター。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。エラー コードの詳細については、ADSI Error Codes を参照してください。
解説(Remarks)
LDAP プロバイダーの場合、bstrRelativeName パラメーターには "CN=Jeff Smith" のような名前プレフィックスを含める必要があります。bstrRelativeName パラメーターには、"CN=Jeff Smith,OU=Sales" のように複数レベルの名前を含めることもできます。
C++ では、GetObject が成功した場合、呼び出し側は QueryInterface メソッドを使用して、IDispatch インターフェイスに目的のインターフェイスを問い合わせる必要があります。
bstrClassName パラメーターには、有効なクラス名または NULL のいずれかを指定できます。クラス名が有効でない場合(空白が含まれている場合を含む)、このメソッドは E_ADS_UNKNOWN_OBJECT エラーをスローします。
例
次のコード例は、コンテナー オブジェクトからユーザー オブジェクトを取得します。
Dim cont As IADsContainer
Dim usr As IADsUser
Set cont = GetObject("LDAP://OU=Sales,DC=Fabrikam,DC=com")
Set usr = cont.GetObject("user", "CN=jeffsmith")
これは次と同等です。
Dim usr As IADsUser
Set usr=GetObject("LDAP://CN=jeffsmith,OU=Sales,DC=Fabrikam,DC=com")
次のコード例は、コンテナー オブジェクトからユーザー オブジェクトを取得します。
HRESULT hr = S_OK;
CoInitialize(NULL);
IADsContainer *pCont = NULL;
hr = ADsGetObject(L"LDAP://DC=windows2000,DC=mytest,DC=fabrikam,DC=com",
IID_IADsContainer,
(void**) &pCont );
if(FAILED(hr))
{
goto Cleanup;
}
///////////////////////////////////////////////////////////////////////
// Retrieve the child from the container.
// Be aware that in the LDAP provider you can navigate multiple levels.
///////////////////////////////////////////////////////////////////////
IDispatch *pDisp = NULL;
IADs *pADs = NULL;
hr = pCont->GetObject(CComBSTR("user"), CComBSTR("CN=Jeff Smith,OU=DSys"), &pDisp);
pCont->Release();
if(FAILED(hr))
{
goto Cleanup;
}
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pDisp->Release();
if(FAILED(hr))
{
goto Cleanup;
}
// Perform an operation with pADs.
pADs->Release();
Cleanup:
if(pCont)
pCont->Release();
if(pDisp)
pDisp->Release();
if(pADs)
pADs->Release();
CoUninitialize();
指定したスキーマ クラスと指定した名前を持つディレクトリ オブジェクトをコンテナー内に作成する要求を設定します。
| ClassName | LPWSTR | in | 作成するスキーマ クラス オブジェクトの名前。この名前は IADs::get_Schema プロパティ メソッドから返されるものです。 |
| RelativeName | LPWSTR | in | 基になるディレクトリで認識されるオブジェクトの相対名で、IADs::get_Name プロパティ メソッドで取得されるものと同一です。 |
| ppObject | IDispatch** | out | 新しく作成されたオブジェクト上の IDispatch インターフェイスへの間接ポインター。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。エラー コードの詳細については、ADSI Error Codes を参照してください。
指定したディレクトリ オブジェクトをこのコンテナーから削除します。
| bstrClassName | LPWSTR | in | 削除するスキーマ クラス オブジェクト。この名前は IADs::get_Class メソッドから返されるものです。また、このパラメーターには NULL も有効な選択肢です。このパラメーターに NULL を指定することは、廃止された(defunct)スキーマ クラスを扱う唯一の方法です。クラスが廃止される前にインスタンスが作成されていた場合、廃止されたクラスのインスタンスを削除する唯一の方法は、IADsContainer::Delete を呼び出して、このパラメーターに NULL を指定することです。 |
| bstrRelativeName | LPWSTR | in | 基になるディレクトリで認識されるオブジェクトの名前で、IADs::get_Name メソッドで取得される名前と同一です。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。エラー コードの詳細については、ADSI Error Codes を参照してください。
解説(Remarks)
削除するオブジェクトは、リーフ オブジェクトまたは子を持たないサブコンテナーである必要があります。コンテナーとその子(つまりサブツリー)を削除するには、IADsDeleteOps::DeleteObject を使用します。
指定したオブジェクトは IADsContainer::Delete の呼び出し後ただちに削除されるため、コンテナー オブジェクトに対して IADs::SetInfo を呼び出す必要はありません。
C/C++ アプリケーションで IADsContainer::Delete メソッドを使用してオブジェクトを削除する場合は、そのオブジェクトへのインターフェイス ポインターも解放してください。これは、このメソッドが基になるディレクトリからオブジェクトをただちに削除する一方で、削除されたオブジェクトについてアプリケーションがメモリ内に保持しているインターフェイス ポインターはそのまま残るためです。解放しない場合、削除されたオブジェクトに対して IADs::Get や IADs::Put をエラーなしで呼び出せる一方、IADs::SetInfo や IADs::GetInfo を呼び出すとエラーが返される、という混乱が生じることがあります。
例
次のコード例は、Active Directory 内のコンテナーからユーザー オブジェクトを削除します。
Dim cont as IADsContainer
On Error GoTo Cleanup
Set cont = GetObject("LDAP://OU=Sales,DC=Fabrikam,DC=com")
cont.Delete "user", "CN=JeffSmith"
Cleanup:
If (Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set cont = Nothing
次のコード例は、WinNT プロバイダー下のコンテナーからユーザー オブジェクトを削除します。
Dim cont as IADsContainer
On Error GoTo Cleanup
Set cont = GetObject("WinNT://Fabrikam")
cont.Delete "user", "jeffsmith"
Cleanup:
If (Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set cont = Nothing
次のコード例は、IADsContainer::Delete を使用してユーザーを削除します。
HRESULT hr = S_OK;
IADsContainer *pCont=NULL;
CoInitialize(NULL);
hr = ADsGetObject(L"WinNT://myMachine",
IID_IADsContainer,
(void**) &pCont);
if ( !SUCCEEDED(hr) )
{
return hr;
}
hr = pCont->Delete(CComBSTR("user"), CComBSTR("JeffSmith"));
pCont->Release();
IADsContainer::CopyHere メソッドは、指定したディレクトリ オブジェクトのコピーをこのコンテナー内に作成します。
| SourceName | LPWSTR | in | コピーするオブジェクトの ADsPath。 |
| NewName | LPWSTR | in | コンテナー内の新しいオブジェクトの名前(省略可能)。オブジェクトに新しい名前を指定しない場合は NULL を設定します。その場合、新しいオブジェクトはソース オブジェクトと同じ名前になります。 |
| ppObject | IDispatch** | out | コピーされたオブジェクト上の IADs インターフェイスへの間接ポインター。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。詳細およびエラー コードについては、ADSI Error Codes を参照してください。
解説(Remarks)
コピー先のコンテナーは、コピー元のコンテナーと同じディレクトリ サービス内にある必要があります。オブジェクトを、ディレクトリ サービスの実装をまたいでコピーすることはできません。
ADSI に付属するプロバイダーは、E_NOTIMPL エラー メッセージを返します。
指定したオブジェクトを、このインターフェイスを実装するコンテナーに移動します。
| SourceName | LPWSTR | in | 移動するオブジェクトの ADsPath を指定する null 終端 Unicode 文字列。 |
| NewName | LPWSTR | in | コンテナー内の新しいオブジェクトの相対名を指定する null 終端 Unicode 文字列。これは NULL にすることができ、その場合オブジェクトは移動されます。NULL でない場合は、その過程でオブジェクトが指定に従って名前変更されます。 |
| ppObject | IDispatch** | out | 移動されたオブジェクト上の IDispatch インターフェイスへのポインターへのポインター。 |
戻り値
このメソッドは、操作が成功した場合の S_OK を含む標準的な戻り値をサポートします。エラー コードの詳細については、ADSI Error Codes を参照してください。
解説(Remarks)
Active Directory では、同じドメイン内でオブジェクトを移動したり、同じディレクトリ フォレスト内の異なるドメイン間で移動したりできます。ドメイン間の移動の場合、次の制限が適用されます。
- 移動先ドメインはネイティブ モードである必要があります。
- 移動するオブジェクトは、リーフ オブジェクトまたは空のコンテナーである必要があります。
- NT LAN Manager (NTLM) では認証を実行できないため、Kerberos 認証または委任を使用してください。Kerberos 認証を使用しない場合、パスワードはネットワーク上を平文で送信されることに注意してください。これを回避するには、セキュリティで保護された認証を伴う委任を使用してください。
- グローバル グループに属するセキュリティ プリンシパル(たとえば、ユーザー、グループ、コンピューターなど)を移動することはできません。セキュリティ プリンシパルが移動されると、移動先でそのオブジェクトに新しい SID が作成されます。ただし、移動元の古い SID は sIDHistory 属性に格納されて保持され、オブジェクトのパスワードも同様に保持されます。
Set ou = GetObject("LDAP://server1/OU=Support,DC=North,DC=Fabrikam,DC=COM")
ou.MoveHere("LDAP://server2/CN=jeffsmith,OU=Sales,DC=South,DC=Fabrikam,DC=Com", vbNullString)
サーバーレスの ADsPath は、移動元、移動先、またはその両方に使用できます。
IADsContainer::MoveHere メソッドは、同じコンテナー内でオブジェクトの名前を変更するためにも、異なるコンテナー間でオブジェクトを移動するためにも使用できます。オブジェクトを移動すると、そのオブジェクトの RDN は保持されますが、オブジェクトの名前を変更すると RDN が変更されます。
たとえば、次のコード例は名前変更の操作を実行します。
set cont = GetObject("LDAP://dc=dom,dc=com")
set newobj = cont.MoveHere("LDAP://cn=Jeff Smith,dc=dom,dc=com", "cn=Denise Smith")
次のコード例は移動を実行します。
set cont = GetObject("LDAP://dc=dom,dc=com")
set newobj = cont.MoveHere("LDAP://cn=jeffsmith,ou=sales,dc=dom,dc=com", "cn=jeffsmith")
Visual Basic アプリケーションでは、あるコンテナーから別のコンテナーへオブジェクトを移動するときに、2 番目のパラメーターとして vbNullString を渡すことができます。
Set newobj = cont.MoveHere("LDAP://cn=jeffsmith,ou=sale,dc=dom,dc=com", vbNullString)
ただし、VBScript では同じことはできません。これは、VBScript が Visual Basic とは異なり、vbNullString を null 文字列ではなく空文字列にマップするためです。前の例に示したように、RDN を明示的に使用する必要があります。
例
次のコード例は、このメソッドを使用してオブジェクトの名前を変更する方法を示します。
Dim cont As IADsContainer
Dim usr As IADsUser
On Error GoTo Cleanup
' Rename an object.
Set cont = GetObject("LDAP://OU=Sales, DC=Fabrikam,DC=com")
Set usr = cont.MoveHere("LDAP://CN=jeffsmith,OU=Sales, DC=Fabrikam,DC=com", "CN=jayhenningsen")
' Move an object.
cont.MoveHere("LDAP://CN=denisesmith,OU=Engineer,DC=Fabrikam,DC=com", vbNullString)
Cleanup:
If (Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set cont = Nothing
Set usr = Nothing
次のコード例は、IADsContainer::MoveHere メソッドを使用してユーザー オブジェクトを移動します。
/////////////////////////////////////////////
// First, bind to the destination container.
////////////////////////////////////////////
HRESULT hr;
IADsContainer *pCont=NULL;
CoInitialize(NULL);
hr = ADsGetObject(
L"LDAP://OU=MCS,DC=windows2000,DC=mytest,DC=fabrikam,DC=com",
IID_IADsContainer,
(void**) &pCont );
if ( !SUCCEEDED(hr) )
{
goto Cleanup;
}
//////////////////////////////////////////////////
// Second, move the object to the bound container.
//////////////////////////////////////////////////
IDispatch *pDisp=NULL;
hr = pCont->MoveHere(CComBSTR("LDAP://CN=Jeff Smith,OU=DSys,DC=windows2000,DC=mytest,DC=fabrikam,DC=com"), NULL, &pDisp );
pCont->Release();
if (SUCCEEDED(hr) )
{
// You can perform another operation here, such as updating attributes.
pDisp->Release();
}
Cleanup:
if(pCont)
pCont->Release();
if(pDisp)
pDisp->Release();
CoUninitialize();
Microsoft 公式リファレンス: 英語 (en-us) · 日本語 (ja-jp) · 原文ソース (GitHub)
HSP用 COM定義
#usecom / #comfunc によるHSPのCOM呼び出し定義。数字は vtbl インデックス(0始まり)。クラスIDが無い場合 #usecom の末尾は "{}"、ある場合は "{CLSID}"。
#define global IID_IADsContainer "{001677D0-FD16-11CE-ABC4-02608C9E7553}" #usecom global IADsContainer IID_IADsContainer "{}" #comfunc global IADsContainer_get_Count 7 var #comfunc global IADsContainer_get__NewEnum 8 sptr #comfunc global IADsContainer_get_Filter 9 var #comfunc global IADsContainer_put_Filter 10 int #comfunc global IADsContainer_get_Hints 11 var #comfunc global IADsContainer_put_Hints 12 int #comfunc global IADsContainer_GetObject 13 wstr,wstr,sptr #comfunc global IADsContainer_Create 14 wstr,wstr,sptr #comfunc global IADsContainer_Delete 15 wstr,wstr #comfunc global IADsContainer_CopyHere 16 wstr,wstr,sptr #comfunc global IADsContainer_MoveHere 17 wstr,wstr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数は var(変数直渡し)。varptr 方式にも切替可。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。 ; ※IDispatch 実装。HSP では comobj 経由でメソッド名による呼び出しも可能(vtbl 不要)。#define global IID_IADsContainer "{001677D0-FD16-11CE-ABC4-02608C9E7553}" #usecom global IADsContainer IID_IADsContainer "{}" #comfunc global IADsContainer_get_Count 7 sptr #comfunc global IADsContainer_get__NewEnum 8 sptr #comfunc global IADsContainer_get_Filter 9 sptr #comfunc global IADsContainer_put_Filter 10 int #comfunc global IADsContainer_get_Hints 11 sptr #comfunc global IADsContainer_put_Hints 12 int #comfunc global IADsContainer_GetObject 13 wstr,wstr,sptr #comfunc global IADsContainer_Create 14 wstr,wstr,sptr #comfunc global IADsContainer_Delete 15 wstr,wstr #comfunc global IADsContainer_CopyHere 16 wstr,wstr,sptr #comfunc global IADsContainer_MoveHere 17 wstr,wstr,sptr ; ※数字は vtbl インデックス(0始まり)。0/1/2 は IUnknown(QueryInterface/AddRef/Release)。 ; ※このインターフェースは直接 CoCreateInstance するクラスIDが無いため "{}"(他メソッド/アクティベーションで取得)。 ; ※出力/バッファ引数はポインタ方式(token=sptr / 呼び出しは varptr(変数))。 ; ※ハンドル/void*等の不透明ポインタは IronHSP では intptr 指定が可能。 ; ※IDispatch 実装。HSP では comobj 経由でメソッド名による呼び出しも可能(vtbl 不要)。