delphi3000.com Article
| Creating windows accounts using ADSI (Active Directory) | |
|---|---|
| Undertitle: | |
| URL: | http://www.delphi3000.com/article.asp?ID=1219 |
| Category: | COM+ |
| Uploader: | Philip Jespersen |
| Question: | How can I create a Windows user account with Delphi and ADSI? |
| Answer: | In order to create Windows user accounts in Delphi you can use the ADSI (Active Directory Services Interface) from Microsoft. You might think that ADSI is only available for Windows 2000 - maybe due to it's name - but actually ADSI is available for all Win32 platforms. You may need to download ADSI for your Windows version (check http://www.microsoft.com/adsi for complete details). ADSI is included with Windows 2000.
ADSI is a very large topic. I'm only stratching the top surface in this article. ADSI is a kind of a generic interface to many different computer (mostly directory based) services. Some of the standard ADSI Providers (COM interfaces which can use in your programs) are WinNT, IIS, LDAP and NDS. The WinNT provider can hereby be used to create user accounts, modify user account settings or modify groups (among a lot of other things). The following small program shows you the steps necessary to create user accounts under NT/2000 using ADSI: First you need import the ADSI Type Library (Menu Project/Import Type Library). The Type Library can be found in the system32 subdirectory (for example C:\WINNT\system32\activeds.tlb). The file required is named 'activeds.tlb'. If you can't find the file check if you've got ADSI installed correctly. After successfully importing the Type Library you'll find a new file in the Delphi Imports directory named activeds_tlb.pas (..\Delphi5\Imports\activeds_tlb.pas for example). Basically you need to include this file in your uses clause in order to enable ADSI programming with Delphi. On to the user creation example with ADSI. You need to replace [computername] with the actual computer name which you are using. The same applies to [accountname]. I've tested the example with WindowsNT 4.0 and Windows 2000. ... uses ActiveX, // used for the COM Moniker stuff... ActiveDs_TLB, // the created type library ComObj; // used for OleCheck and other COM functions implementation procedure TForm1.BtnCreateUserClick(Sender: TObject); var Usr: IADsUser; Comp: IADsContainer; begin try Comp := GetObject('WinNT://[computername],computer') as IADsContainer; Usr := Comp.Create('user', '[accountname]') as IADsUser; Usr.SetInfo; except on E: EOleException do begin ShowMessage(E.Message); end; end; end; procedure TForm1.BtnSetPasswordClick(Sender: TObject); var Usr: IADsUser; begin try Usr := GetObject('WinNT://[computername]/[accountname],user') as IADsUser; Usr.SetPassword('thenewpassword'); except on E: EOleException do begin ShowMessage(E.Message); end; end; end; // GetObject is a implementation of the VB GetObject call // I've found this code (GetObject) on the Usenet. // // With GetObject can you bind to an existing ADSI provider // using a 'ADSIPath' (for example WinNT://.... or // IIS://localhost). function TForm1.GetObject(const Name: string): IDispatch; var Moniker: IMoniker; Eaten: integer; BindContext: IBindCtx; Dispatch: IDispatch; begin OleCheck(CreateBindCtx(0, BindContext)); OleCheck(MkParseDisplayName(BindContext, PWideChar(WideString(Name)), Eaten, Moniker)); OleCheck(Moniker.BindToObject(BindContext, NIL, IDispatch, Dispatch)); Result := Dispatch; end; end. Over ADSI you can also modify the settings of a user account. The following code can be used to change the 'Password never expires' flag of any account: procedure TFormMain.ButtonNeverExpiresClick(Sender: TObject); var Usr: IADsUser; begin try Usr := GetObject('WinNT://[computername]/[acccoutname],user') as IADsUser; // Check the Checkbox State... if CheckBoxPasswordNeverExpires.Checked then Usr.Put('UserFlags', Usr.Get('UserFlags') OR 65536) // 65536 is defined as UF_DONT_EXPIRE_PASSWORD in iads.h // from the ADSI SDK available from Microsoft else Usr.Put('UserFlags', Usr.Get('UserFlags') XOR 65536); Usr.SetInfo; except on E: EOleException do begin ShowMessage(E.Message); end; end; end; From here... In order to get into the deeper parts of ADSI you need to check out the actual interfaces provided like IADsUser or IADsContainer. I recommend that you work with the ADSI SDK from Microsoft and by inspecting the created Type Library. |
| Copyright 2000 delphi3000.com Contact: delphi3000@bluestep.com' |
| Comments to this article |
|---|
Biplab Saha (Apr 13 2007 9:04AM) | ||
Helio guys i nedd some help i am trying it so many days but i cant implement it.If possible then please help me .My problem is that i have to implement a form using delphi 7 and i have to show "List of all group of the current loogin user in ative directory" So i am requesting all of guys that plz give me a solution how i implement it. Thanks Biplab Kumar Saha <%If Session("sSecurityLevel") >= 2 Then%> |
David escobar beristain (Jan 2 2007 10:52PM) | ||
tengo problemas al declarar la variable, con los ejemplos que se muestran: Var salesOu: IADsContainer; usr: IADsUser; Try salesOU:= GetObject('LDAP://OU=OU MDF,OU=OU Personal del CECA,OU=OU Centro de Computo Academico,DC=yyy,DC=com') As IADsContainer; usr:= salesOU.Create('user', 'CN=Donald Duck') As IADsUser; usr.Put('sAMAccountName','dd'); usr.Put('userPrincipalName','dd@yyy.com'); usr.Put('title','Marketing Manager'); usr.Put('givenName','Donald'); usr.Put('sn','Duck'); usr.Put('DisplayName','Donald Duck'); usr.Put('initials','DD'); usr.Put('Description','Funny duck'); usr.Put('scriptPath','dd\logon.cmd'); usr.SetInfo; usr.SetPassword('Password'); usr.AccountDisabled:= False; usr.SetInfo; Except On E: EOleException Do Begin ShowMessage(E.Message); End; End; El error que me manda es el siguiente [Error] Unit1.pas(118): Undeclared identifier: 'IADsContainer' [Error] Unit1.pas(119): Undeclared identifier: 'IADsUser' por favor alguien me podra ayudar. RE: Activi directory |
Marina Pryadko (Jun 9 2005 11:16AM) | ||
Hi! What properties shoud I set to query select only those data which are one level lower then the container determined in query. For example: Company.com - Department1 - Department11 - Department12 - Department2 - Department21 Select distinguishedName From 'LDAP://DC=Company, DC=com' WHERE ObjectClass='OrganizationalUnit' returns OU=Department1,DC=Company, DC=com OU=Department11,OU=Department1,DC=Company, DC=com OU=Department12,OU=Department1,DC=Company, DC=com OU=Department2,DC=Company, DC=com OU=Department21,OU=Department2,DC=Company, DC=com I want the query to return OU=Department1,DC=Company, DC=com OU=Department2,DC=Company, DC=com Please help me with my problem RE: One-level query to Active Directory |
delpai (May 25 2005 7:45AM) | ||
I get an error with this code. Can anyone help me with it? How can I get rid off the error? ADsGetObject('WinNT://' + Domain + '/' + disp.Name, IADsUser, usr); try node.Strings[colEmail] := usr.EmailAddress; ... <%If Session("sSecurityLevel") >= 2 Then%> |
gela charkviani (Apr 19 2005 10:34PM) | ||
i can't create user accounts :( anyone knows why? begin try Comp := GetObject('WinNT://' + GetCompName + ',computer') as IADsContainer; Usr := Comp.Create('user3', 'MyName') as IADsUser; Usr.SetInfo; ............................ and i get an EOleException telling that one or more arguments ar invalid. Usr := Comp.Create('user3', 'MyName') as IADsUser; <-- something is wrong here. anyone can help me please? <%If Session("sSecurityLevel") >= 2 Then%> |
Donald Neisler (Oct 28 2004 5:54PM) | ||
If write a app to reset/change passwords, doesn't it need to run as a administrator or someone that has rights to do so? Is there a way to mask a user so that a non admin can run this program to reset/change a password? TIA Donald <%If Session("sSecurityLevel") >= 2 Then%> |
Martyn MacCabe (Sep 7 2004 12:35PM) | ||
I have a script that creates a batch of new users based on information provided in a spreadsheet. I now wish to create a new script or update my existing script so that it will add all of the users to a list of specified global groups. Looking for a bit of help to start me off or even if anyone can point me to an example script it would be much obliged. Thanks <%If Session("sSecurityLevel") >= 2 Then%> |
yannick LANCHEC (Sep 2 2004 12:55AM) | ||
How can i change the user's password with ADSI to be blank ? i have try ADS_UF_PASSWD_NOTREQD with the userAccountControl but i always have an error 80070057 thanks !! <%If Session("sSecurityLevel") >= 2 Then%> |
ALEXANDRE NISHIKAWA (Aug 17 2004 10:39PM) | ||
I have a lot of Directory and I need to search a user in a diferents context, is have a function? <%If Session("sSecurityLevel") >= 2 Then%> |
Emma (Dec 5 2003 1:03PM) | ||
Is is possible to add new properties på AD-users through ldap? And if it is, how do I do this? thanks, Emma <%If Session("sSecurityLevel") >= 2 Then%> |
Thomas Olsen (Aug 15 2003 6:20PM) | ||
procedure TForm1.AddToGroupClick(Sender: TObject); Var grp: IADsGroup; begin Try grp:= GetObject('LDAP://CN=Management,OU=Sales,DC=T-point,DC=Dk') as IADsGroup; grp.Add('LDAP://CN=Donald Duck,OU=Sales,DC=T-point,DC=Dk'); Except On E: EOleException Do Begin ShowMessage(E.Message); End; End; end; <%If Session("sSecurityLevel") >= 2 Then%> |
Thomas Olsen (Aug 15 2003 6:20PM) | ||
procedure TForm1.CreateGroupClick(Sender: TObject); Var Ou: IADsContainer; Grp: IADsGroup; begin Try ou:= GetObject('LDAP://OU=Sales,DC=T-point,DC=Dk') As IADsContainer; Grp:= ou.Create('group', 'CN=Management') Ss IADsGroup; Grp.Put('samAccountName', 'mgmt'); Grp.Put('groupType', ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP Or ADS_GROUP_TYPE_SECURITY_ENABLED); Grp.SetInfo; Except On E: EOleException Do Begin ShowMessage(E.Message); End; End; end; <%If Session("sSecurityLevel") >= 2 Then%> |
Thomas Olsen (Aug 15 2003 6:19PM) | ||
procedure TForm1.CreateUserClick(Sender: TObject); Var salesOu: IADsContainer; usr: IADsUser; begin Try salesOU:= GetObject('LDAP://OU=Sales,DC=T-Point,DC=Dk') As IADsContainer; usr:= salesOU.Create('user', 'CN=Donald Duck') As IADsUser; usr.Put('sAMAccountName','dd'); usr.Put('userPrincipalName','dd@t-point.dk'); usr.Put('title','Marketing Manager'); usr.Put('givenName','Donald'); usr.Put('sn','Duck'); usr.Put('DisplayName','Donald Duck'); usr.Put('initials','DD'); usr.Put('Description','Funny duck'); usr.Put('scriptPath','dd\logon.cmd'); usr.SetInfo; usr.SetPassword('Password'); usr.AccountDisabled:= False; usr.SetInfo; Except On E: EOleException Do Begin ShowMessage(E.Message); End; End; end; RE: Create User |
Thomas Olsen (Aug 15 2003 6:18PM) | ||
procedure TForm1.CreateOUClick(Sender: TObject); Var Dom: IADsContainer; salesOu: IADsOu; begin Try dom:= GetObject('LDAP://DC=T-Point,DC=Dk') As IADsContainer; salesOu:= dom.Create('organizationalUnit', 'OU=Sales') As IADsOu; salesOu.Put('description', 'Sales Headquarter'); salesOu.Put('wwwHomePage', 'http://www.t-point.dk'); salesOu.SetInfo; Except On E: EOleException Do Begin ShowMessage(E.Message); End; End; end; <%If Session("sSecurityLevel") >= 2 Then%> |
Marsha Thompson (Jan 14 2003 10:44PM) | ||
After looking at article, I was able to connect to domain and create a user in the domain, however, I need, to enhance this, to create the user in an Organizational Unit instead of root level. Could you help me with this? I am real close, however, get an error with my syntax when try to add OrganizationalUnit. Could you tell me how to add Organizational Unit. Here is syntax that works. //Domain=FCA.ORG //OrganizationalUnit = Users procedure TForm1.btnCreateNewUserClick(Sender: TObject); var adComp : IADsContainer; var adUser : IADsUser; begin //Connect to Active Directory FCA Domain adComp := GetObject('LDAP://FCA.ORG') as IADsContainer; Messagedlg('Just got adComp-this works fine', mtInformation, [mbOK], 0); adUser := adComp.Create('user', 'CN=Jay Adams') as IADsUser; Messagedlg('Just created User', mtInformation, [mbOK], 0); adUser.Put('samAccountName', 'jayadams'); adUser.Put('userPrincipalName', 'jayadams@fca.org'); adUser.Put('title', 'Marketing Manager'); adUser.SetInfo; Messagedlg('Just added a User-this works fine', mtInformation, [mbOK], 0); end; function TForm1.GetObject(Name: string): IDispatch; var Moniker: IMoniker; Eaten: integer; BindContext: IBindCtx; Dispatch: IDispatch; begin OleCheck(CreateBindCtx(0, BindContext)); OleCheck(MkParseDisplayName(BindContext, PWideChar(WideString(Name)), Eaten, Moniker)); OleCheck(Moniker.BindToObject(BindContext, NIL, IDispatch, Dispatch)); Result := Dispatch; end; end. RE: Active Directory - Organizational Unit |
anonymus (Nov 20 2001 11:56AM) | ||
I heared that if we use WinNT Provider, we cannot placed new user in any container or organizational unit and if we want to placed new user in any Container or Organizational unit we must use LDAP Provider Would you please inform me how to use LDAP to create and delete new user ? Thank you very much <%If Session("sSecurityLevel") >= 2 Then%> |
Martijn Houtman (Nov 18 2000 9:04PM) | ||
function TForm1.GetObject(const Name: string): IDispatch; var Dispatch: IDispatch; begin OleCheck(CoGetObject(PWideString(WideString(Name)), nil, IDispatch, @Dispatch)); Result := Dispatch; end; RE: You can also use CoGetObject |
Aven (Oct 16 2000 3:10AM) | ||
How can I know the current login user information ? RE: How can I know the current login user information ? |
Deepak Shenoy (Aug 6 2000 1:25PM) | ||
This is a good beginning - but if you need to enumerate the users in a domain or group, you`ll need to use IEnumVariant. There are some standard ADSI functions for enumeration, located in ADsHlp.h in the PlatformSDK. I`ve converted them to Delphi - to get them mail me at shenoy@agnisoft.com. I even have a paper on it at www.agnisoft.com/adsi - I`ve still got to spend some time updating the site though :) DNS |