Mega Code Archive

 
Categories / Delphi / LAN Web TCP
 

Query against the Active Directory by LDAP

Title: Query against the Active Directory by LDAP Question: How can i get the current or all user account(s) in a Active Directory Domain? Answer: To find Information in the Active Directory is easy if you know the distinguishedname of the object(s). So you can use the ADSI Interface to connect to the object(s). If you want to know all existing computer- or/and user accounts in your Domain, anything else or information of the current logged in user, it is more difficult. In this case ADSI is not comfortable because ADSI searches only the specified path and ignores subfolders e.g. search path= LDAP://DC=yourdomain, DC=domainextension will not searches the default user container below the search path in the AD. Using LDAP Queries by Delphis ADO components is a solution to find all existing computers or/and users or information of the current logged in user. With LDAP you can find anything else in the AD, you only need to know how to built SQL-Statements. The following Example is written in Delphi 2005 German professional Edition in a Windows Server 2003 Environment. The Form has a TButton, 2xTListbox, TADOConnection and TADOCommand components included. (sorry, on the configuration description you will find the Delphi german captions) configuration of the TADOConnection1 component -Open the property ConnectionString -Choose the button Aufbauen(to establish?) -On the Provider Tab choose OLE DB Provider for Microsoft Directory Services Thats it To specify a explicit Domain Controller you can choose the tab Verbindung(connection?) and insert the netbios name of a Domain Controller configuration of the TADOCommand component -name=cmd -other settings will be set on button1onclick Routine for easier understanding The important thing on LDAP Queries is the default PageSize by Microsoft. The PageSize property of the DomainController class in a Microsoft Windows Server 2003 Environments gets or sets the page size in a paged search. For each request by the client, the server returns, at most, the number of objects as set by the page size. The default PageSize is limited to 10. This means, the resultset of a LDAP Query has a default Resultset of max. 1000 entries per page. In small Environments probably thats no problem, but in other cases you receive a wrong score. I dont find in Delphi a solution like Pearl has to define a routine to scroll through the pagecount. I built a solution with Delphi that dont need to scroll through. So i dont need VB, Perl or ********************************************************************* procedure Tfm_main.Button1Click(Sender: TObject); var SQL,DOMAIN,USER:string; t:_recordset; begin DOMAIN:='''LDAP://dc=yourdomain, dc=domainextension; listbox1.Clear; listbox2.Clear; try cmd.Connection:=adoconnection1; adoconnection1.Connected:=true; //The sql statements selects all user accounts in the //specified domain. //Important: the objectclass must be included in ' signs SQL:='select cn,distinguishedname from '+DOMAIN+' where objectclass='+'''user'''+' and objectclass'+'''computer'''; cmd.CommandText:=SQL; //-The default delphi property of cmd.Properties.Item['Page //Size'].Value is 0! so the resultset has a max. of 1000 entries. //-Define a value for the default pagesize to ensure to get all //search arguments in one page. //-10 gaves me a resultset of more than 28.8000 entrees. //-The item['Page Size'] has a space between. With no space it // raises an error cmd.Properties.Item['Page Size'].Value:=10; t:=cmd.Execute; while t.EOF = false do begin if t.Fields[1].Value NULL then listbox1.Items.Add(t.Fields[0].Value+' '+t.Fields[1].Value); t.MoveNext; end; listbox1.Items.Insert(0,'Count of items: '+inttostr(listbox1.Items.count)); //***************************************************************** // // the following code provides some information of the current logged //in user and can be used for further queries // //****************************************************************** USER:=''''+username+''''; SQL:='select displayname,createtimestamp,distinguishedname from '+DOMAIN+' where objectclass='+'''user'''+' and cn='+USER; cmd.CommandText:=SQL; t:=cmd.Execute; if t.RecordCount 0 then begin //-Normally the the resultset is filled in order of the query //arguments and starts with 0 //-The filling of the resultset by the DomainController starts //with the last(!) search argument of the SQL Select order. //-In this example the argument -displayname- is not //resultset[0] but resultset[2] listbox2.Items.Add('Account: '+USER); listbox2.Items.Add(' -Created at: '+datetostr(t.Fields[1].value)+' '+timetostr(t.Fields[1].value)); listbox2.Items.Add(' -Displayname: '+t.Fields[2].value); listbox2.Items.Add(' -Distinguishedname: '+t.Fields[0].value); end else listbox2.Items.Add('Search argument '+USER+' not found'); adoconnection1.Connected:=false; except on exception do showmessage('Error'); end; end; //this function provides the current logged in user function Tfm_main.username:string; var userName: array[1..100] of Char ; arrSize: DWord; begin arrSize := SizeOf(UserName); GetUserName(@UserName, arrSize); result:=copy(username,1,arrsize-1); end;