本文只介绍如何读取,写入域控信息,不对域控等相关概念作介绍。读写主要是对账户属性信息的介绍,其他属性类似,可以通过AD属性对照表去读写其他属性。
一、创建单元ActiveDs_TLB.pas
XE中的创建步骤:Component->Import Component->Import a Type Library->Active DS Type Libeaey下一步创建单元就可以了。
D7中的创建步骤:Component->Import ActiveX Control->Active DS Type Libeaey创建单元就可以了。
二、添加DLL接口
需要用到两个方法,一个是ADsOpenObject用来连接域控;一个是ADsGetObject用来获取域控对象。声明如下:
function ADsOpenObject(lpszPathName: PWideChar; //第一个参数是对象的路径名
lpszUserName: PWideChar; //第二个参数是调用者提供的用户名
lpszPassword: PWideChar; //第三个参数是调用者提供的口令
dwReserved: LongInt; //第四个参数是一个保留的 provider 标识,用来确定绑定的认证方法
const riid: TIID; //第五个参数是请求接口的接口标识符,
out obj): HResult; stdcall; external 'activeds.dll'; //最后一个参数用来返回请求的接口指针。
function ADsGetObject(lpszPathName: PWideChar; //第一个参数是对象的路径名
const riid: TIID; //第二个参数是对象的接口标识符
out obj): HResult; stdcall; external 'activeds.dll';// 第三个参数用于返回得到的被请求的接口指针
三、读取信息
1、读取组织单元,用户等信息。通过IADs接口返回信息。
// 使用用户登录的信息创建域对象
OleCheck(AdsOpenObject(PWideChar(aDomainPath),
PWideChar(aUser),
PWideChar(aPass),
0,
IID_IADsContainer,
UnknownObject));
// 设定域对象
Domain := UnknownObject as IADsContainer;
//获取枚举对象,并赋值给 Enum 变量
Enum := (Domain._NewEnum) as IEnumVariant;
//利用枚举对象查找,把每个子对象赋值给临时的 OLEVariant 对象
while (Enum.Next(1, ADsTempObj, Value) = S_OK) do
begin
ADsObj := IUnknown(ADsTempObj) as IADs; //获得临时对象:OLEVariant 变量赋值给 ADSI 对象
RichEdit3.Lines.Add(AdsObj.Name+'('+AdsObj.Class_+')'); //对象类型
if AdsObj.Class_ = 'organizationalUnit' then //如果是组织单元对象
begin
OUItem.Lines.Add(ADsObj.Name) ;
AddDepToTreeView(ADsObj);
end;
if AdsObj.Class_ = 'user' then //如果是用户对象 displayName sAMAccountName objectSID
begin
UserItem.Lines.Add(ADsObj.Name+'(sAMAccountName='+ADsObj.Get('sAMAccountName')+') ' );
UserItem.Lines.Add(ADsObj.Name+'(userPrincipalName='+ADsObj.Get('userPrincipalName')+')' );
UserItem.Lines.Add(ADsObj.Name+'(userAccountControl='+intToStr( ADsObj.Get('userAccountControl') )+')' );
UserItem.Lines.Add(ADsObj.Name+'(logonHours='+ByteToString(ADsObj.Get('logonHours') )+')' );
UserItem.Lines.Add(ADsObj.Name+'(accountExpires='+datetimeToStr(VariantToDatetime(ADsObj.Get('accountExpires')))+')' );
//showmessage(ADsObj.Get('ObjectSID'));
end;
//递归。得到组内相关用户。
GetADInfo(aUser,aPass,ADsObj.ADsPath);
ADsTempObj:=Null; //释放OLEVariant
end;
通过IADs接口返回信息时在账户属性中需要注意的两个属性。
logonHours属性返回的是array byte ,接收返回值是要传相应的类型。
accountExpires属性返回的是Filetime的时间类型,可以通过转换成Localtime在转成datetime。
function VariantToDatetime(V: Variant): Tdatetime;
var
LargeInteger: IADsLargeInteger;
ft: TFileTime;
LocalFileTime: TFileTime;
SystemTime: TSystemTime;
DateTime: TDateTime;
begin
LargeInteger := IDispatch(v) as IADsLargeInteger;
ft.dwLowDateTime := LargeInteger.LowPart;
ft.dwHighDateTime := LargeInteger.HighPart;
if Int64(ft) = 0 then
Result := 0
else
begin
//Memo1.Lines.Add('AccountExpiration:'+intToStr(Int64(ft)));
FileTimeToLocalFileTime(ft, LocalFileTime);
if FileTimeToSystemTime(LocalFileTime, SystemTime) then
DateTime := SystemTimeToDateTime(SystemTime);
Result := DateTime;
end;
end;
2、读取信息通过IADsUser接口。
这种方式可以通过点属性的方式读取相应属性值。
User.AccountExpirationDate;
四、设置属性值。
主要介绍对账户的属性设置举例。
var
UnknownObject: IUnknown;
DomainPath,ADUser,ADPass: WideString;
path:string;
Container : IADsContainer;
User : IADsUser;
adate:Double;
begin
OUItem.Clear;
UserItem.Clear;
TreeView1.Items.Clear;
RichEdit3.Clear;
DomainPath:='LDAP://';
reorderstr(AreaName.Text,path);
DomainPath:=DomainPath+serverName.Text+'/OU='+StringReplace(path,'/',',OU=',[rfReplaceAll])
+',DC='+StringReplace(Edit1.Text,'.',',DC=',[rfReplaceAll]);
if userName.Text<>'' then
ADUser:=userName.Text+'@'+Edit1.Text;
if passWord.Text<>'' then
ADPass:=passWord.Text;
OleCheck(AdsOpenObject(PWideChar(DomainPath),
PWideChar(ADUser),
PWideChar(ADPass),
0,
IID_IADsContainer,
UnknownObject));
ADsGetObject(PWideChar(DomainPath),IADsContainer,Container);
User:=Container.GetObject('user','CN='+Edit2.Text) as IADsUser;
User.GetInfo;
User.AccountDisabled:=false;
User.Description:='wnjnfn';
User.LoginHours:=StrToByte('//0/0');
Memo1.Lines.Add('======'+datetimetostr(User.AccountExpirationDate));
adate:=0;
User.AccountExpirationDate:=strTodatetime('1601/1/1 8:00:00'); //设置永不过期
//如果设置其他过期时间就正常时间就可以了。这个 AccountExpirationDate是datetime类型。
User.SetInfo;
Memo1.Lines.Add('编辑用户【'+Edit2.Text+'】成功');
end;
五、删除用户,组织单元,组等节点操作。
这里只以删除用户举例,其他类似,只是类型改下就可以。
var
UnknownObject: IUnknown;
DomainPath,ADUser,ADPass: WideString;
path:string;
Container : IADsContainer;
begin
OUItem.Clear;
UserItem.Clear;
TreeView1.Items.Clear;
RichEdit3.Clear;
DomainPath:='LDAP://';
reorderstr(AreaName.Text,path);
DomainPath:=DomainPath+serverName.Text+'/OU='+StringReplace(path,'/',',OU=',[rfReplaceAll])
+',DC='+StringReplace(Edit1.Text,'.',',DC=',[rfReplaceAll]);
if userName.Text<>'' then
ADUser:=userName.Text+'@'+Edit1.Text;
if passWord.Text<>'' then
ADPass:=passWord.Text;
OleCheck(AdsOpenObject(PWideChar(DomainPath),
PWideChar(ADUser),
PWideChar(ADPass),
0,
IID_IADsContainer,
UnknownObject));
ADsGetObject(PWideChar(DomainPath),IADsContainer,Container);
//如果删除别的,只需要把user改成别的类型就可以
Container.Delete('user','CN='+Edit2.Text);
Memo1.Lines.Add('删除用户【'+Edit2.Text+'】成功');
end;