Vous êtes sur la page 1sur 13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)

Printing Details URL: http://www.ianatkinson.net/computing/adcsharp.htm Date: 12 Dec 2013 9:45 All content Ian Atkinson 20002013, not to be re-used without permission

Active Directory With C#


Introduction T wo Different Approaches Mixed Approach System.DirectoryServices Examples
i. ii. iii. iv. v. vi. vii. Changing the Filter The createDirectoryEntry Function Example 1 - Retrieving All Information From a Users Record Example 2 - Retrieving Selected Information From a Users Record Example 3 - Retrieving Information for All Users Example 4 - Updating a User Example 5 - Adding a New User

System.DirectoryServices.AccountManagement Examples
i. Example 6 - Retrieving Information From a Users Record ii. Example 7 - Retrieving Information From All Users Again iii. Example 8 - Using Both Libraries

Introduction
If you work in the kind of large institution that I do and are using M icrosoft Active Directory then the chances are that at certain times you will need to perform actions on the directory that are outside the scope of the M SAD tools. This could be things like specialised queries, bulk account creation or mass updates of user information. The M SAD tools and even some of the command line tools are quite limiting and difficult to use in this regard. Whatever the reason, you may find that at some point you need to either purchase additional software for managing AD or write your own. Obviously Id rather write my own software as its cheaper, more rewarding and you can customise it however you like! I found that when I was trying to learn how to make C# work nicely with AD there were a lack of simple tutorials to get me started, although I did find a few useful blog posts. Often any examples that I found did much more in the program than I was after, so it was difficult to pick out the few lines that I was actually interested in. So, this page contains a few basic but fully working programs which illustrate common scenarios that you may have. If you can read and understand these examples you should be able to apply the principles to much larger and very powerful programs as I have done. Obviously you need to be careful with this kind of programming and where ever possible you shouldnt be testing on a live environment. Queries are safe enough but when you get on to account creation and modification the potential to royally muck up a lot of account very quickly is a real danger, so take care!

Two Approaches
What is a little bit confusing is that there are essentially two sets of classes which can be used for AD operations. One is easier to use but not as versatile, the other is harder to use but lets you do pretty much anything (within my experience anyway!). Which approach you use will depend on your project requirements. If you literally want to write a password resetting tool or a simple phone book then the A c c o u n t M a n a g e m e n tlibraries probably contain everything you need so you should use those. For anything more complicated you may find that you need to get a bit more down and dirty with the LDAP and use the D i r e c t o r y S e r v i c e sapproach.

System.DirectoryServices
M SDN Documentation The older and more difficult approach is using just S y s t e m . D i r e c t o r y S e r v i c e son its own. This lets you do pretty much anything that you like however the approach is more technical. For example the properties of the AD objects (description, telephone etc.) are all held in an array which can present its own problems and involve a lot of iteration and use of casting since they are all generic objects. Using this approach doing things like setting the password or enabling/disbaling the account is much more cryptic in the way in which it is achieved, often requiring UAC codes to be manually set and so on.

www.ianatkinson.net/computing/adcsharp.htm

1/13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)

System.DirectoryServices.AccountManagement
M SDN Documentation The newer approach is to use S y s t e m . D i r e c t o r y S e r v i c e s . A c c o u n t M a n a g e m e n twhich was designed to make managing AD through .NET much easier. Rather than accessing properties using an array they are exposed directly within the classes (and typed accordingly), allowing us to use things like u s e r . D i s p l a y N a m ewhich is much tidier. We also have easy to use methods available such as . S e t P a s s w o r d ( )and . U n l o c k A c c o u n t ( )as well as the . E n a b l e dproperty which can be used to easily manage accounts. These are self explanatory in use once you have retrieved the object from AD so are not included in the examples! The problem as I said though is that whilst the A c c o u n t M a n a g e m e n tlibrary makes things much easier in some regards it is also quite limited in others. It exposes only a small number of the LDAP fields that you may want to use (name, description, email, home dir and phone is about it) so if you need access to a more obscure property it wont suffice.

Mixed Approach
One thing thats worth noting is that you can use the newer libraries to get a U s e r P r i n c i p a lobject as they are called, and then access the underlying LDAP object with the . G e t U n d e r l y i n g O b j e c t ( )method. This means that you could start a program with the newer approach but if you find it too limiting drop into the older approach half way through and have full access. This is not a very neat approach but does work well, we will have a look at how this works in example 8. Hopefully if the newer libraries are expanded further in future .NET released there should be less and less reason to ever need to do this!

System.DirectoryServices Examples
These first examples all use the older approach and will serve you best if you are writing a large or complex AD management program.

Adjusting the Filter


In all of the examples where the program asks for a username the program then matches this to the field c n , which is what the AD GUI refers to as Full Name and is what is listed as name in the tabulated account lising of Active Directory Users and Computers. You could change the username to something else by adjusting the filter. For example if you wanted to enter a user logon name (called s a m a c c o u n t n a m ein the schema), you could set the filter as follows:
s e a r c h . F i l t e r=" ( s a m a c c o u n t n a m e = "+u s e r n a m e+" ) " ;

The createDirectoryEntry Function


All of these examples contain the same function called c r e a t e D i r e c t o r y E n t r y , located at the bottom of the program. In order to try out the examples you will need to edit this function and enter both a hostname for your own AD server and also an appropriate search path. I have left in as examples the paths that I used when creating the programs. If you are logged into a system as a domain administrator or a user with appropriate privilages then you should not need to specify a username and password for the connection. However, if you are running the program as an unprivilaged user then you will need to add (or prompt for and program accordingly) a username and password to the D i r e c t o r y E n t r yobject. The function is overloaded several times so you can just append as follows:
D i r e c t o r y E n t r yl d a p C o n n e c t i o n=n e wD i r e c t o r y E n t r y ( " s e r v e r " ," u s e r n a m e " ," p a s s w o r d " ) ;

Example one : Retrieving All Information From a Users Record


This first example will introduce you to the classes needed for querying the AD using C#. I will explain this example fully as this will give a good understanding of the other examples also, once you grasp the major principles involved. What we are going to do first is retrieve a full LDAP entry for a particular user. This isnt something that you would want to do very often as it isnt at all selective and would be overkill when querying a lot of users. This is useful however if you need to find out what a particular field in the Active Directory is called. For example, in the AD GUI we can set a PO Box as part of the address (in College we use this for pigeon hole numbers). When you wish to query this information in your C# program the field is actually called p o s t o f f i c e b o x .

www.ianatkinson.net/computing/adcsharp.htm

2/13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)

There is no tool that I know of which shows the correlation between the fields in the GUI and what the fields are called in the schema, so it has been necessary for me several times during development to set one of the fields to foo and then run a full query looking for foo in order to reveal the correct field. The example is not too hard to understand, however there are several different classes used in order to accomplish the task. First we create a D i r e c t o r y E n t r yobject. As you will have guessed from the section above regarding your setting, this class will contain all of the information which describes the server we are trying to connect to such as address, username and so on. We then create a D i r e c t o r y S e a r c h e robject. This class describes a search and operates against the D i r e c t o r y E n t r yobject, so it knows where to search, and has its own properties such as its F i l t e rso it knows what to search for. We then use the class S e a r c h R e s u l tagainst the D i r e c t o r y S e a r c h e robject, which represents an LDAP entry. This object has a number of P r o p e r t i e s(such as user name, e-mail address) and a number of generic objects associated with each property: S earchResult result Properties Objects cn mail Ian Atkinson santa@clause.ac.uk users memberof staff domain administrators

The properties have generic objects associated with them as the class has no concept of their content. If you wish you will need to cast or convert to more specific classes in order to perform some operations, for example a telephone extension could be cast to an i n t . In many cases there will be a single object associated with each property, for example a user can have only one user logon name (or s a m a c c o u n t n a m e ). However some properties, such as m e m b e r o fwhich represents a users group membership, will have many objects (one for each group in this case). The S e a r c h R e s u l tobject operates like an array, so we can retrieve a particular value such as r e s u l t . P r o p e r t i e s [ " c n " ] [ 0 ]for the first object associated with the c n property. In the example above r e s u l t . P r o p e r t i e s [ " m e m b e r o f " ] [ 1 ]is "staff". We can also iterate through all of the objects associated with a given property by using the R e s u l t P r o p e r t y C o l l e c t i o nclass, which is what we do in the example below. NB: this first example is more heavily commented than the rest in order to outline the common parts. In subsequent examples I have removed the comments and only commented the new or relevant parts. retrieve_all_info.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 .

u s i n gS y s t e m ; u s i n gS y s t e m . T e x t ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ;

www.ianatkinson.net/computing/adcsharp.htm

3/13

12/12/2013
0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 . 4 0 . 4 1 . 4 2 . 4 3 . 4 4 . 4 5 . 4 6 . 4 7 . 4 8 . 4 9 . 5 0 . 5 1 . 5 2 . 5 3 . 5 4 . 5 5 . 5 6 . 5 7 . 5 8 . 5 9 . 6 0 . 6 1 . 6 2 . 6 3 . 6 4 . 6 5 . 6 6 . 6 7 . 6 8 . 6 9 . 7 0 . 7 1 .

Querying and Updating Active Directory Using C# (C Sharp)


n a m e s p a c ea c t i v e D i r e c t o r y L d a p E x a m p l e s { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { C o n s o l e . W r i t e ( " E n t e ru s e r :" ) ; S t r i n gu s e r n a m e=C o n s o l e . R e a d L i n e ( ) ; t r y { / /c r e a t eL D A Pc o n n e c t i o no b j e c t D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n=c r e a t e D i r e c t o r y E n t r y ( ) ; / /c r e a t es e a r c ho b j e c tw h i c ho p e r a t e so nL D A Pc o n n e c t i o no b j e c t / /a n ds e ts e a r c ho b j e c tt oo n l yf i n dt h eu s e rs p e c i f i e d D i r e c t o r y S e a r c h e rs e a r c h=n e wD i r e c t o r y S e a r c h e r ( m y L d a p C o n n e c t i o n ) ; s e a r c h . F i l t e r=" ( c n = "+u s e r n a m e+" ) " ; / /c r e a t er e s u l t so b j e c t sf r o ms e a r c ho b j e c t S e a r c h R e s u l tr e s u l t=s e a r c h . F i n d O n e ( ) ; i f( r e s u l t! =n u l l ) { / /u s e re x i s t s ,c y c l et h r o u g hL D A Pf i e l d s( c n ,t e l e p h o n e n u m b e re t c . ) R e s u l t P r o p e r t y C o l l e c t i o nf i e l d s=r e s u l t . P r o p e r t i e s ; f o r e a c h( S t r i n gl d a p F i e l di nf i e l d s . P r o p e r t y N a m e s ) { / /c y c l et h r o u g ho b j e c t si ne a c hf i e l de . g .g r o u pm e m b e r s h i p / /( f o rm a n yf i e l d st h e r ew i l lo n l yb eo n eo b j e c ts u c ha sn a m e ) f o r e a c h( O b j e c tm y C o l l e c t i o ni nf i e l d s [ l d a p F i e l d ] ) C o n s o l e . W r i t e L i n e ( S t r i n g . F o r m a t ( " { 0 , 2 0 }:{ 1 } " , l d a p F i e l d ,m y C o l l e c t i o n . T o S t r i n g ( ) ) ) ; } } e l s e { / /u s e rd o e sn o te x i s t C o n s o l e . W r i t e L i n e ( " U s e rn o tf o u n d ! " ) ; } } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : \ n \ n "+e . T o S t r i n g ( ) ) ; } } s t a t i cD i r e c t o r y E n t r yc r e a t e D i r e c t o r y E n t r y ( ) { / /c r e a t ea n dr e t u r nn e wL D A Pc o n n e c t i o nw i t hd e s i r e ds e t t i n g s D i r e c t o r y E n t r yl d a p C o n n e c t i o n =n e wD i r e c t o r y E n t r y ( " r i z z o . l e e d s a r t . a c . u k " ) ; l d a p C o n n e c t i o n . P a t h =" L D A P : / / O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k " ; l d a p C o n n e c t i o n . A u t h e n t i c a t i o n T y p e=A u t h e n t i c a t i o n T y p e s . S e c u r e ; r e t u r nl d a p C o n n e c t i o n ; } } }

Here is an (abbreviated) example of the output:


H : \ D e s k t o p \ a d c s h a r p > r e t r i e v e _ a l l _ i n f o E n t e ru s e r :I a nA t k i n s o n d i s t i n g u i s h e d n a m e c n m a i l n i c k n a m e d i s p l a y n a m e t i t l e s a m a c c o u n t n a m e g i v e n n a m e m a i l s n p o s t o f f i c e b o x :C N = I a nA t k i n s o n , O U = I T , O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k :I a nA t k i n s o n :i a n a :I a nA t k i n s o n :S e n i o rI n f r a s t r u c t u r eS u p p o r tE n g i n e e r :i a n a :I a n :s a n t a @ c l a u s e . a c . u k :A t k i n s o n :J 1 0

www.ianatkinson.net/computing/adcsharp.htm

4/13

12/12/2013
< s n i p >

Querying and Updating Active Directory Using C# (C Sharp)

Example 2 - Retrieving Selected Information From a Users Record


This example is almost identical to the above example, however we are now selective about which fields from the AD we want to bring in. This is a much more realistic example as its obviously bad practise to query more data than is required. We load certain properties by calling the P r o p e r t i e s T o L o a d . A d dmethod on our D i r e c t o r y S e a r c h e r object. retrieve_some_info.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 . 4 0 . 4 1 . 4 2 . 4 3 . 4 4 . 4 5 . 4 6 . 4 7 . 4 8 . 4 9 . 5 0 . 5 1 . 5 2 . 5 3 . 5 4 . 5 5 . 5 6 . 5 7 .

u s i n gS y s t e m ; u s i n gS y s t e m . T e x t ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ; n a m e s p a c ea c t i v e D i r e c t o r y L d a p E x a m p l e s { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { C o n s o l e . W r i t e ( " E n t e ru s e r :" ) ; S t r i n gu s e r n a m e=C o n s o l e . R e a d L i n e ( ) ; t r y { D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n=c r e a t e D i r e c t o r y E n t r y ( ) ; D i r e c t o r y S e a r c h e rs e a r c h=n e wD i r e c t o r y S e a r c h e r ( m y L d a p C o n n e c t i o n ) ; s e a r c h . F i l t e r=" ( c n = "+u s e r n a m e+" ) " ; / /c r e a t ea na r r a yo fp r o p e r t i e st h a tw ew o u l dl i k ea n d / /a d dt h e mt ot h es e a r c ho b j e c t s t r i n g [ ]r e q u i r e d P r o p e r t i e s=n e ws t r i n g [ ] { " c n " ," p o s t o f f i c e b o x " ," m a i l " } ; f o r e a c h( S t r i n gp r o p e r t yi nr e q u i r e d P r o p e r t i e s ) s e a r c h . P r o p e r t i e s T o L o a d . A d d ( p r o p e r t y ) ; S e a r c h R e s u l tr e s u l t=s e a r c h . F i n d O n e ( ) ; i f( r e s u l t! =n u l l ) { f o r e a c h( S t r i n gp r o p e r t yi nr e q u i r e d P r o p e r t i e s ) f o r e a c h( O b j e c tm y C o l l e c t i o ni nr e s u l t . P r o p e r t i e s [ p r o p e r t y ] ) C o n s o l e . W r i t e L i n e ( S t r i n g . F o r m a t ( " { 0 , 2 0 }:{ 1 } " , p r o p e r t y ,m y C o l l e c t i o n . T o S t r i n g ( ) ) ) ; } e l s eC o n s o l e . W r i t e L i n e ( " U s e rn o tf o u n d ! " ) ; } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : \ n \ n "+e . T o S t r i n g ( ) ) ; } } s t a t i cD i r e c t o r y E n t r yc r e a t e D i r e c t o r y E n t r y ( ) { / /c r e a t ea n dr e t u r nn e wL D A Pc o n n e c t i o nw i t hd e s i r e ds e t t i n g s D i r e c t o r y E n t r yl d a p C o n n e c t i o n =n e wD i r e c t o r y E n t r y ( " r i z z o . l e e d s a r t . a c . u k " ) ; l d a p C o n n e c t i o n . P a t h =" L D A P : / / O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k " ; l d a p C o n n e c t i o n . A u t h e n t i c a t i o n T y p e=A u t h e n t i c a t i o n T y p e s . S e c u r e ; r e t u r nl d a p C o n n e c t i o n ; } } }

Here is an example of the output:


H : \ D e s k t o p \ a d c s h a r p > r e t r i e v e _ s o m e _ i n f o E n t e ru s e r c n p o s t o f f i c e b o x m a i l :I a nA t k i n s o n :I a nA t k i n s o n :J 1 0 :s a n t a @ c l a u s e . a c . u k

Example 3 - Retrieving Information for All Users


So far we have only retrieved information for a single user. In this example we will retrieve some information for all of the

www.ianatkinson.net/computing/adcsharp.htm

5/13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)


users in our search base. We can accomplish this simply by using the F i n d A l lrather than the F i n d O n emethod on our D i r e c t o r y S e a r c h e robject and then iterating through the results. all_users.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 . 4 0 . 4 1 . 4 2 . 4 3 . 4 4 . 4 5 . 4 6 . 4 7 . 4 8 . 4 9 . 5 0 . 5 1 .

u s i n gS y s t e m ; u s i n gS y s t e m . T e x t ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ; n a m e s p a c ea c t i v e D i r e c t o r y L d a p E x a m p l e s { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { C o n s o l e . W r i t e ( " E n t e rp r o p e r t y :" ) ; S t r i n gp r o p e r t y=C o n s o l e . R e a d L i n e ( ) ; t r y { D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n=c r e a t e D i r e c t o r y E n t r y ( ) ; D i r e c t o r y S e a r c h e rs e a r c h=n e wD i r e c t o r y S e a r c h e r ( m y L d a p C o n n e c t i o n ) ; s e a r c h . P r o p e r t i e s T o L o a d . A d d ( " c n " ) ; s e a r c h . P r o p e r t i e s T o L o a d . A d d ( p r o p e r t y ) ; S e a r c h R e s u l t C o l l e c t i o na l l U s e r s=s e a r c h . F i n d A l l ( ) ; f o r e a c h ( S e a r c h R e s u l tr e s u l ti na l l U s e r s ) { i f( r e s u l t . P r o p e r t i e s [ " c n " ] . C o u n t>0& &r e s u l t . P r o p e r t i e s [ p r o p e r t y ] . C o u n t>0 ) { C o n s o l e . W r i t e L i n e ( S t r i n g . F o r m a t ( " { 0 , 2 0 }:{ 1 } " , r e s u l t . P r o p e r t i e s [ " c n " ] [ 0 ] . T o S t r i n g ( ) , r e s u l t . P r o p e r t i e s [ p r o p e r t y ] [ 0 ] . T o S t r i n g ( ) ) ) ; } } } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : \ n \ n "+e . T o S t r i n g ( ) ) ; } } s t a t i cD i r e c t o r y E n t r yc r e a t e D i r e c t o r y E n t r y ( ) { / /c r e a t ea n dr e t u r nn e wL D A Pc o n n e c t i o nw i t hd e s i r e ds e t t i n g s D i r e c t o r y E n t r yl d a p C o n n e c t i o n=n e wD i r e c t o r y E n t r y ( " r i z z o . l e e d s a r t . a c . u k " ) ; l d a p C o n n e c t i o n . P a t h=" L D A P : / / O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k " ; l d a p C o n n e c t i o n . A u t h e n t i c a t i o n T y p e=A u t h e n t i c a t i o n T y p e s . S e c u r e ; r e t u r nl d a p C o n n e c t i o n ; } } }

Here is an example of the output:


H : \ D e s k t o p \ a d c s h a r p > a l l _ u s e r s E n t e rp r o p e r t y I a nA t k i n s o n R u d o l p h E l f :m a i l :s a n t a @ c l a u s e . a c . u k :r u d o l p h @ c l a u s e . a c . u k :e l f @ c l a u s e . a c . u k

Example 4 - Updating a User


Having covered querying the AD we will now move on to updating the AD! This is much simpler than you might imagine as the search results that we have already found really represent actual objects on the server, so we can easily edit the properties of the result and then write this information back to the AD. We do this by creating a D i r e c t o r y E n t r yobject from the search result (using the G e t D i r e c t o r y E n t r y method) and then setting the V a l u efor any property that we would like to change. When we are finished we use the C o m m i t C h a n g e smethod to actually write the changes. In this small example we retrieve a users job title (t i t l ein the schema) and then change it for a new one.

www.ianatkinson.net/computing/adcsharp.htm

6/13

12/12/2013
update_user.cs:

Querying and Updating Active Directory Using C# (C Sharp)

view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 . 4 0 . 4 1 . 4 2 . 4 3 . 4 4 . 4 5 . 4 6 . 4 7 . 4 8 . 4 9 . 5 0 . 5 1 . 5 2 . 5 3 . 5 4 . 5 5 . 5 6 . 5 7 . 5 8 . 5 9 . 6 0 . 6 1 . 6 2 . 6 3 . 6 4 . 6 5 . 6 6 .

u s i n gS y s t e m ; u s i n gS y s t e m . T e x t ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ; n a m e s p a c ea c t i v e D i r e c t o r y L d a p E x a m p l e s { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { C o n s o l e . W r i t e ( " E n t e ru s e r :" ) ; S t r i n gu s e r n a m e=C o n s o l e . R e a d L i n e ( ) ; t r y { D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n=c r e a t e D i r e c t o r y E n t r y ( ) ; D i r e c t o r y S e a r c h e rs e a r c h=n e wD i r e c t o r y S e a r c h e r ( m y L d a p C o n n e c t i o n ) ; s e a r c h . F i l t e r=" ( c n = "+u s e r n a m e+" ) " ; s e a r c h . P r o p e r t i e s T o L o a d . A d d ( " t i t l e " ) ; S e a r c h R e s u l tr e s u l t=s e a r c h . F i n d O n e ( ) ; i f( r e s u l t! =n u l l ) { / /c r e a t en e wo b j e c tf r o ms e a r c hr e s u l t D i r e c t o r y E n t r ye n t r y T o U p d a t e=r e s u l t . G e t D i r e c t o r y E n t r y ( ) ; / /s h o we x i s t i n gt i t l e C o n s o l e . W r i t e L i n e ( " C u r r e n tt i t l e :"+ e n t r y T o U p d a t e . P r o p e r t i e s [ " t i t l e " ] [ 0 ] . T o S t r i n g ( ) ) ; C o n s o l e . W r i t e ( " \ n \ n E n t e rn e wt i t l e:" ) ; / /g e tn e wt i t l ea n dw r i t et oA D S t r i n gn e w T i t l e=C o n s o l e . R e a d L i n e ( ) ; e n t r y T o U p d a t e . P r o p e r t i e s [ " t i t l e " ] . V a l u e=n e w T i t l e ; e n t r y T o U p d a t e . C o m m i t C h a n g e s ( ) ; C o n s o l e . W r i t e L i n e ( " \ n \ n . . . n e wt i t l es a v e d " ) ; } e l s eC o n s o l e . W r i t e L i n e ( " U s e rn o tf o u n d ! " ) ; } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : \ n \ n "+e . T o S t r i n g ( ) ) ; } } s t a t i cD i r e c t o r y E n t r yc r e a t e D i r e c t o r y E n t r y ( ) { / /c r e a t ea n dr e t u r nn e wL D A Pc o n n e c t i o nw i t hd e s i r e ds e t t i n g s D i r e c t o r y E n t r yl d a p C o n n e c t i o n =n e wD i r e c t o r y E n t r y ( " r i z z o . l e e d s a r t . a c . u k " ) ; l d a p C o n n e c t i o n . P a t h =" L D A P : / / O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k " ; l d a p C o n n e c t i o n . A u t h e n t i c a t i o n T y p e=A u t h e n t i c a t i o n T y p e s . S e c u r e ; r e t u r nl d a p C o n n e c t i o n ; } } }

Here is an (abbreviated) example of the output. Note how when the program is run for the second time the title that is retrieved is the one entered the first time around:
H : \ D e s k t o p \ a d c s h a r p > u p d a t e _ u s e r E n t e ru s e r C u r r e n tt i t l e :I a nA t k i n s o n :S e n i o rI n f r a s t r u c t u r eS u p p o r tE n g i n e e r

E n t e rn e wt i t l e:D o g s b o d y . . . n e wt i t l es a v e d

www.ianatkinson.net/computing/adcsharp.htm

7/13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)


H : \ D e s k t o p \ a d c s h a r p > u p d a t e _ u s e r E n t e ru s e r C u r r e n tt i t l e :I a nA t k i n s o n :D o g s b o d y

E n t e rn e wt i t l e:S e n i o rI n f r a s t r u c t u r eS u p p o r tE n g i n e e r . . . n e wt i t l es a v e d

Example 5 - Adding a New User


One of the most complex things that you may decide you need to do is add a new user from your C# program, rather than using the AD tools. Again, there are various commercial programs to do this and also tools in the Resource Kit than can be scripted with, but you may find that you just cant find something to do absolutely everything that you need, just how you need it done. The program below should be a good starting point for anyone wanting to add in their own users. It shows you how to:
Create a user with custom options Set a password Enable the account Add the user to some groups Create a home folder Set the ownserhip of the home folder Set the permissions/ACL of the home folder

Obviously if you wanted to use this as a basis for your own program you would need to set the options to your own requirements and tweak as necessary. Specifically if you want to write a flexible program to write users in and out of different OUs, rather than a single OU, then it will be necessary to create multiple LDAP connections with different paths, and also a more complex function to add users to groups which searches the whole subtree. create_user.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 . 4 0 . 4 1 .

u s i n gS y s t e m ; u s i n gS y s t e m . T e x t ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ; u s i n gS y s t e m . I O ; u s i n gS y s t e m . S e c u r i t y . A c c e s s C o n t r o l ; u s i n gS y s t e m . S e c u r i t y . P r i n c i p a l ; n a m e s p a c ea c t i v e D i r e c t o r y L d a p E x a m p l e s { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { / /c o n n e c tt oL D A P D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n=c r e a t e D i r e c t o r y E n t r y ( ) ; / /d e f i n ev a r sf o ru s e r S t r i n gd o m a i n =" l e e d s a r t . a c . u k " ; S t r i n gf i r s t =" T e s t " ; S t r i n gl a s t =" U s e r " ; S t r i n gd e s c r i p t i o n=" . N E TT e s t " ; o b j e c t [ ]p a s s w o r d ={" 1 2 3 4 5 6 7 8 "} ; S t r i n g [ ]g r o u p s ={" S t a f f "} ; S t r i n gu s e r n a m e =f i r s t . T o L o w e r ( )+l a s t . S u b s t r i n g ( 0 ,1 ) . T o L o w e r ( ) ; S t r i n gh o m e D r i v e =" H : " ; S t r i n gh o m e D i r =@ " \ \ g o n z o . l e e d s a r t . a c . u k \ d a t a 3 \ U S E R S \ "+u s e r n a m e ; / /c r e a t eu s e r t r y { i f( c r e a t e U s e r ( m y L d a p C o n n e c t i o n ,d o m a i n ,f i r s t ,l a s t ,d e s c r i p t i o n , p a s s w o r d ,g r o u p s ,u s e r n a m e ,h o m e D r i v e ,h o m e D i r ,t r u e )= =0 ) { C o n s o l e . W r i t e L i n e ( " A c c o u n tc r e a t e d ! " ) ; C o n s o l e . R e a d L i n e ( ) ; }

www.ianatkinson.net/computing/adcsharp.htm

8/13

12/12/2013
4 2 . 4 3 . 4 4 . 4 5 . 4 6 . 4 7 . 4 8 . 4 9 . 5 0 . 5 1 . 5 2 . 5 3 . 5 4 . 5 5 . 5 6 . 5 7 . 5 8 . 5 9 . 6 0 . 6 1 . 6 2 . 6 3 . 6 4 . 6 5 . 6 6 . 6 7 . 6 8 . 6 9 . 7 0 . 7 1 . 7 2 . 7 3 . 7 4 . 7 5 . 7 6 . 7 7 . 7 8 . 7 9 . 8 0 . 8 1 . 8 2 . 8 3 . 8 4 . 8 5 . 8 6 . 8 7 . 8 8 . 8 9 . 9 0 . 9 1 . 9 2 . 9 3 . 9 4 . 9 5 . 9 6 . 9 7 . 9 8 . 9 9 . 1 0 0 . 1 0 1 . 1 0 2 . 1 0 3 . 1 0 4 . 1 0 5 . 1 0 6 . 1 0 7 . 1 0 8 . 1 0 9 . 1 1 0 . 1 1 1 . 1 1 2 . 1 1 3 . 1 1 4 . 1 1 5 . 1 1 6 . 1 1 7 . 1 1 8 . 1 1 9 . 1 2 0 . 1 2 1 . 1 2 2 . 1 2 3 . 1 2 4 . 1 2 5 .

Querying and Updating Active Directory Using C# (C Sharp)


e l s e { C o n s o l e . W r i t e L i n e ( " P r o b l e mc r e a t i n ga c c o u n t: ( " ) ; C o n s o l e . R e a d L i n e ( ) ; } } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : \ n \ n "+e . T o S t r i n g ( ) ) ; C o n s o l e . R e a d L i n e ( ) ; } } s t a t i ci n tc r e a t e U s e r ( D i r e c t o r y E n t r ym y L d a p C o n n e c t i o n ,S t r i n gd o m a i n ,S t r i n gf i r s t , S t r i n gl a s t ,S t r i n gd e s c r i p t i o n ,o b j e c t [ ]p a s s w o r d , S t r i n g [ ]g r o u p s ,S t r i n gu s e r n a m e ,S t r i n gh o m e D r i v e , S t r i n gh o m e D i r ,b o o le n a b l e d ) { / /c r e a t en e wu s e ro b j e c ta n dw r i t ei n t oA D D i r e c t o r y E n t r yu s e r=m y L d a p C o n n e c t i o n . C h i l d r e n . A d d ( " C N = "+f i r s t+""+l a s t ," u s e r " ) ; / /U s e rn a m e( d o m a i nb a s e d ) u s e r . P r o p e r t i e s [ " u s e r p r i n c i p a l n a m e " ] . A d d ( u s e r n a m e+" @ "+d o m a i n ) ; / /U s e rn a m e( o l d e rs y s t e m s ) u s e r . P r o p e r t i e s [ " s a m a c c o u n t n a m e " ] . A d d ( u s e r n a m e ) ; / /S u r n a m e u s e r . P r o p e r t i e s [ " s n " ] . A d d ( l a s t ) ; / /F o r e n a m e u s e r . P r o p e r t i e s [ " g i v e n n a m e " ] . A d d ( f i r s t ) ; / /D i s p l a yn a m e u s e r . P r o p e r t i e s [ " d i s p l a y n a m e " ] . A d d ( f i r s t+""+l a s t ) ; / /D e s c r i p t i o n u s e r . P r o p e r t i e s [ " d e s c r i p t i o n " ] . A d d ( d e s c r i p t i o n ) ; / /E m a i l u s e r . P r o p e r t i e s [ " m a i l " ] . A d d ( f i r s t+" . "+l a s t+" @ "+d o m a i n ) ; / /H o m ed i r( d r i v el e t t e r ) u s e r . P r o p e r t i e s [ " h o m e d i r e c t o r y " ] . A d d ( h o m e D i r ) ; / /H o m ed i r( p a t h ) u s e r . P r o p e r t i e s [ " h o m e d r i v e " ] . A d d ( h o m e D r i v e ) ; u s e r . C o m m i t C h a n g e s ( ) ; / /s e tu s e r ' sp a s s w o r d u s e r . I n v o k e ( " S e t P a s s w o r d " ,p a s s w o r d ) ; / /e n a b l ea c c o u n ti fr e q u e s t e d( s e eh t t p : / / s u p p o r t . m i c r o s o f t . c o m / k b / 3 0 5 1 4 4f o ro t h e rc o d e s ) i f( e n a b l e d ) u s e r . I n v o k e ( " P u t " ,n e wo b j e c t [ ]{" u s e r A c c o u n t C o n t r o l " ," 5 1 2 "} ) ; / /a d du s e rt os p e c i f i e dg r o u p s f o r e a c h( S t r i n gt h i s G r o u pi ng r o u p s ) { D i r e c t o r y E n t r yn e w G r o u p=m y L d a p C o n n e c t i o n . P a r e n t . C h i l d r e n . F i n d ( " C N = "+t h i s G r o u p ," g r o u p " ) ; i f( n e w G r o u p! =n u l l ) n e w G r o u p . I n v o k e ( " A d d " ,n e wo b j e c t [ ]{u s e r . P a t h . T o S t r i n g ( )} ) ; } u s e r . C o m m i t C h a n g e s ( ) ; / /m a k eh o m ef o l d e ro ns e r v e r D i r e c t o r y . C r e a t e D i r e c t o r y ( h o m e D i r ) ; / /s e tp e r m i s s i o n so nf o l d e r ,w el o o pt h i sb e c a u s ei ft h ep r o g r a m / /t r i e st os e tt h ep e r m i s s i o n ss t r a i g h ta w a ya ne x c e p t i o nw i l lb e / /t h r o w na st h eb r a n dn e wu s e rd o e sn o ts e e mt ob ea v a i l a b l e ,i tt a k e s / /as e c o n do rs of o ri tt oa p p e a ra n di tc a nt h e nb eu s e di nA C L s / /a n ds e ta st h eo w n e r

www.ianatkinson.net/computing/adcsharp.htm

9/13

12/12/2013
1 2 6 . 1 2 7 . 1 2 8 . 1 2 9 . 1 3 0 . 1 3 1 . 1 3 2 . 1 3 3 . 1 3 4 . 1 3 5 . 1 3 6 . 1 3 7 . 1 3 8 . 1 3 9 . 1 4 0 . 1 4 1 . 1 4 2 . 1 4 3 . 1 4 4 . 1 4 5 . 1 4 6 . 1 4 7 . 1 4 8 . 1 4 9 . 1 5 0 . 1 5 1 . 1 5 2 . 1 5 3 . 1 5 4 . 1 5 5 . 1 5 6 . 1 5 7 . 1 5 8 . 1 5 9 . 1 6 0 . 1 6 1 . 1 6 2 . 1 6 3 . 1 6 4 . 1 6 5 . 1 6 6 . 1 6 7 . 1 6 8 . 1 6 9 . 1 7 0 . 1 7 1 . 1 7 2 . 1 7 3 . 1 7 4 . 1 7 5 . 1 7 6 . 1 7 7 . 1 7 8 . 1 7 9 . 1 8 0 . 1 8 1 . 1 8 2 . 1 8 3 . 1 8 4 .

Querying and Updating Active Directory Using C# (C Sharp)


b o o lf o l d e r C r e a t e d=f a l s e ; w h i l e( ! f o l d e r C r e a t e d ) { t r y { / /g e tc u r r e n tA C L D i r e c t o r y I n f od I n f o=n e wD i r e c t o r y I n f o ( h o m e D i r ) ; D i r e c t o r y S e c u r i t yd S e c u r i t y=d I n f o . G e t A c c e s s C o n t r o l ( ) ; / /A d df u l lc o n t r o lf o rt h eu s e ra n ds e to w n e rt ot h e m I d e n t i t y R e f e r e n c en e w U s e r=n e wN T A c c o u n t ( d o m a i n+@ " \ "+u s e r n a m e ) ; d S e c u r i t y . S e t O w n e r ( n e w U s e r ) ; F i l e S y s t e m A c c e s s R u l ep e r m i s s i o n s= n e wF i l e S y s t e m A c c e s s R u l e ( n e w U s e r ,F i l e S y s t e m R i g h t s . F u l l C o n t r o l , A c c e s s C o n t r o l T y p e . A l l o w ) ; d S e c u r i t y . A d d A c c e s s R u l e ( p e r m i s s i o n s ) ; / /S e tt h en e wa c c e s ss e t t i n g s . d I n f o . S e t A c c e s s C o n t r o l ( d S e c u r i t y ) ; f o l d e r C r e a t e d=t r u e ; } c a t c h( S y s t e m . S e c u r i t y . P r i n c i p a l . I d e n t i t y N o t M a p p e d E x c e p t i o n ) { C o n s o l e . W r i t e ( " . " ) ; } c a t c h( E x c e p t i o ne x ) { / /o t h e re x c e p t i o nc a u g h ts on o tp r o b l e mw i t hu s e rd e l a ya s / /c o m m e n t e da b o v e C o n s o l e . W r i t e L i n e ( " E x c e p t i o nc a u g h t : "+e x . T o S t r i n g ( ) ) ; r e t u r n1 ; } } r e t u r n0 ; } s t a t i cD i r e c t o r y E n t r yc r e a t e D i r e c t o r y E n t r y ( ) { / /c r e a t ea n dr e t u r nn e wL D A Pc o n n e c t i o nw i t hd e s i r e ds e t t i n g s D i r e c t o r y E n t r yl d a p C o n n e c t i o n =n e wD i r e c t o r y E n t r y ( " r i z z o . l e e d s a r t . a c . u k " ) ; l d a p C o n n e c t i o n . P a t h =" L D A P : / / O U = s t a f f u s e r s , D C = l e e d s a r t , D C = a c , D C = u k " ; l d a p C o n n e c t i o n . A u t h e n t i c a t i o n T y p e=A u t h e n t i c a t i o n T y p e s . S e c u r e ; r e t u r nl d a p C o n n e c t i o n ; } } }

System.DirectoryServices.AccountManagement Examples
This second set of examples all use the newer libraries and will serve you best if you are writing smaller or simpler programs.

Example 6 - Retrieving Information From a Users Record


This first example is similar to example 2 but using the newer libraries. The approach to searching for a user is a little different as you can see. Here we will just retrieve a persons name and phone number from their logon name. First a P r i n c i p a l C o n t e x tobject is created, this is the connection to AD and is overloaded many times so that you can pass it an LDAP path, user name and password if required (omitted from the example to keep it simple). We then create a U s e r P r i n c i p a lobject and set some criteria on it. This can be confusing as when we have retrieved a user from AD it will be an object of the same type, however this object is not real and is only used for searching. This effectively replaces the LDAP search filter. So we make the object and set its s a m a c c o u n t n a m ewhich allows us to search in the P r i n c i p a l C o n t e x tfor a user with that logon name. Finally we create the P r i n c i p a l S e a r c h e robject and run it using the search user we just created. The result is then cast into a new U s e r P r i n c i p a lobject which represents the acutal AD user. The cast is used as the same approach is also used to find G r o u p P r i n c i p a lor C o m p u t e r P r i n c i p a lobjects. This may sound complicated but hopefully when you read below you will see it is only a few lines of code!

www.ianatkinson.net/computing/adcsharp.htm

10/13

12/12/2013
newer_details.cs:

Querying and Updating Active Directory Using C# (C Sharp)

view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 .

u s i n gS y s t e m ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s . A c c o u n t M a n a g e m e n t ; n a m e s p a c en e w _ a d _ e x m a p l e { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { t r y { / /e n t e rA Ds e t t i n g s P r i n c i p a l C o n t e x tA D=n e wP r i n c i p a l C o n t e x t ( C o n t e x t T y p e . D o m a i n ," l e e d s a r t . a c . u k " ) ; / /c r e a t es e a r c hu s e ra n da d dc r i t e r i a C o n s o l e . W r i t e ( " E n t e rl o g o nn a m e :" ) ; U s e r P r i n c i p a lu=n e wU s e r P r i n c i p a l ( A D ) ; u . S a m A c c o u n t N a m e=C o n s o l e . R e a d L i n e ( ) ; / /s e a r c hf o ru s e r P r i n c i p a l S e a r c h e rs e a r c h=n e wP r i n c i p a l S e a r c h e r ( u ) ; U s e r P r i n c i p a lr e s u l t=( U s e r P r i n c i p a l ) s e a r c h . F i n d O n e ( ) ; s e a r c h . D i s p o s e ( ) ; / /s h o ws o m ed e t a i l s C o n s o l e . W r i t e L i n e ( " D i s p l a yN a m e:"+r e s u l t . D i s p l a y N a m e ) ; C o n s o l e . W r i t e L i n e ( " P h o n eN u m b e r:"+r e s u l t . V o i c e T e l e p h o n e N u m b e r ) ; } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E r r o r :"+e . M e s s a g e ) ; } } } }

And the output:


E n t e rl o g o nn a m e :i a n a D i s p l a yN a m e:I a nA t k i n s o n P h o n eN u m b e r:1 2 3 4

Example 7 - Retrieving Info From All Users Again


This example is similar to example 3, here we show all peoples phone numbers. To find all objects we have still created the search object but have simply not specified any criteria for it (other than the AD it belongs to) so the search returns all objects. We can then iterate over these with a handy f o r e a c h . In real life you should limit the scope of a search like this of course by specifying the correct OU rather than searching the whole AD, but I'm trying to keep the example code concise! newer_phones.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 .

u s i n gS y s t e m ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s . A c c o u n t M a n a g e m e n t ; n a m e s p a c en e w _ a d _ e x m a p l e { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { t r y { P r i n c i p a l C o n t e x t A D =n e wP r i n c i p a l C o n t e x t ( C o n t e x t T y p e . D o m a i n ," l e e d s a r t . a c . u k " ) ; U s e r P r i n c i p a l u =n e wU s e r P r i n c i p a l ( A D ) ; P r i n c i p a l S e a r c h e rs e a r c h=n e wP r i n c i p a l S e a r c h e r ( u ) ; f o r e a c h ( U s e r P r i n c i p a lr e s u l ti ns e a r c h . F i n d A l l ( ) ) i f( r e s u l t . V o i c e T e l e p h o n e N u m b e r! =n u l l ) C o n s o l e . W r i t e L i n e ( " { 0 , 3 0 }{ 1 }" ,r e s u l t . D i s p l a y N a m e ,r e s u l t . V o i c e T e l e p h o n e N u m b e r ) ; s e a r c h . D i s p o s e ( ) ; }

www.ianatkinson.net/computing/adcsharp.htm

11/13

12/12/2013
2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 .

Querying and Updating Active Directory Using C# (C Sharp)


c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E r r o r :"+e . M e s s a g e ) ; } } } }

And some abbreviated output:


J o eB l o g g s1 2 4 5 J i mB l o g g s1 4 5 6 J a nB l o g g s1 7 6 5 B o bB l o g g s1 2 9 8

Example 8 - Using Both Libraries


Here we will see how a U s e r P r i n c i p a lcan be converted into a more general object so that we can access properties which are not exposed by the A c c o u n t M a n a g e m e n tlibraries. There should be no reason to do this in future if the libraries are expanded to expose more properties! This example will now list the persons mail box along with the phone number by expanding the previous example, as I said earlier this is the field p o s t o f f i c e b o xin AD which is not exposed by A c c o u n t M a n a g e m e n t . In addition to the previous example we now get the underlying object from the U s e r P r i n c i p a lwhich we call l o w e r L d a p . Since . G e t U n d e r l y i n g O b j e c t ( )returns a generic object we have to cast this to a D i r e c t o r y E n t r y(the S y s t e m . D i r e c t o r y S e r v i c e sequivalent of a U s e r P r i n c i p a las seen in the earlier examples above) so that we can access its p r o p e r t i e sarray. newer_dropdown.cs:
view plain

0 1 . 0 2 . 0 3 . 0 4 . 0 5 . 0 6 . 0 7 . 0 8 . 0 9 . 1 0 . 1 1 . 1 2 . 1 3 . 1 4 . 1 5 . 1 6 . 1 7 . 1 8 . 1 9 . 2 0 . 2 1 . 2 2 . 2 3 . 2 4 . 2 5 . 2 6 . 2 7 . 2 8 . 2 9 . 3 0 . 3 1 . 3 2 . 3 3 . 3 4 . 3 5 . 3 6 . 3 7 . 3 8 . 3 9 .

u s i n gS y s t e m ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s ; u s i n gS y s t e m . D i r e c t o r y S e r v i c e s . A c c o u n t M a n a g e m e n t ; n a m e s p a c en e w _ a d _ e x m a p l e { c l a s sP r o g r a m { s t a t i cv o i dM a i n ( s t r i n g [ ]a r g s ) { t r y { P r i n c i p a l C o n t e x t A D =n e wP r i n c i p a l C o n t e x t ( C o n t e x t T y p e . D o m a i n ," l e e d s a r t . a c . u k " ) ; U s e r P r i n c i p a l u =n e wU s e r P r i n c i p a l ( A D ) ; P r i n c i p a l S e a r c h e rs e a r c h=n e wP r i n c i p a l S e a r c h e r ( u ) ; f o r e a c h( U s e r P r i n c i p a lr e s u l ti ns e a r c h . F i n d A l l ( ) ) { i f( r e s u l t . V o i c e T e l e p h o n e N u m b e r! =n u l l ) { D i r e c t o r y E n t r yl o w e r L d a p=( D i r e c t o r y E n t r y ) r e s u l t . G e t U n d e r l y i n g O b j e c t ( ) ; C o n s o l e . W r i t e L i n e ( " { 0 , 3 0 }{ 1 }{ 2 } " , r e s u l t . D i s p l a y N a m e , r e s u l t . V o i c e T e l e p h o n e N u m b e r , l o w e r L d a p . P r o p e r t i e s [ " p o s t o f f i c e b o x " ] [ 0 ] . T o S t r i n g ( ) ) ; } } s e a r c h . D i s p o s e ( ) ; } c a t c h( E x c e p t i o ne ) { C o n s o l e . W r i t e L i n e ( " E r r o r :"+e . M e s s a g e ) ; } } } }

And some abbreviated output:


J o eB l o g g s1 2 4 5J 1 0 J i mB l o g g s1 4 5 6J 1 1 J a nB l o g g s1 7 6 5J 1 2 B o bB l o g g s1 2 9 8J 1 3

www.ianatkinson.net/computing/adcsharp.htm

12/13

12/12/2013

Querying and Updating Active Directory Using C# (C Sharp)

www.ianatkinson.net/computing/adcsharp.htm

13/13

Vous aimerez peut-être aussi