in

ASP.NET Weblogs

Brian Desmond's Blog

Inherits Network.Admin
Implements IOneManBand

December 2003 - Posts

  • Creating a Contact in AD

    Well, this new Agg Views thing indicates that my babbling about Active Directory stuff is mildly interesting, so, I'm continuing the series here. This morning's task is creating a contact in AD. Before we get going, let me give a brief overview of my take on what Contacts are for. Feel free to reference the Platform SDK for whatever the official word is.

    Without an Exchange Server, I think contacts are pretty darn useless, unless you intend to keep the corporate rolodex in AD, which, I guess is feasible. A contact is like a user, except it doesn't have an account in your domain. Contacts have all the attributes a contact in your rolodex would have - name, address, email, phone, etc. But, unlike a user, they cannot log on to the domain. When an Exchange Server comes into play, contacts become a lot more useful. You can do a couple of things with them - create a forwarding address for a user object, or simple create a forwarding address. They also are ten times as useful as a “contact” in the corporate rolodex, as they can be displayed in the GAL along with other users.

    So, here's what we're going to do: create a contact object in AD. You can follow this example pretty easily and modify it to create a user or a group if you want. Tomorrow (or next time), we'll dive into CDOEXM and mail enable the contact, and setup a user with forwarding. Not sure what's next - perhaps create a user & a mailbox to go along with it.

    First thing we're going to do is setup a directoryEntry for the OU we're creating the contact in. We'll create our contact in an OU called Contacts in the root of our domain MyDomain.local:

    Dim root as new DirectoryEntry(LDAP://OU=Contacts,DC=MyDomain,DC=local)

    The key to creating something in AD is to create another DirectoryEntry off of the Add method of our root's Children property:

    Dim myContact as DirectoryEntry = root.Children.Add("CN=Jane Doe", "contact")

    What we've done here is created a new container of class contact inside the Contacts OU. I always name my contacts and user CNs the same as their display name in the GAL. So, Jane Doe's contact object is in container (CN) Jane Doe.

    Now we can set some properties. I'm just going to set the first (givenName) and last (surName) name attributes like we did last night. For demo, I'll also set Jane's home phone to 773-555-1212 (that's Chicago directory assistance if you want to call)

    myContact.Properties(”givenName”).Value = “Jane”
    myContact.Properties(”sn”).Value = “Doe”
    myContact.Properties(“homePhone“).Value = “773-555-1212“
    myContact.CommitChanges()

    This is the same as last night - nothing to go over, just remmeber to call CommitChanges(), or nothing will get pushed to the directory.

    So, in conclusion, we've used the code below to create a contact for Jane Doe in the Contacts organizational unit (OU), whose home phone is 773-555-1212. 

    Dim root as new DirectoryEntry(“LDAP://OU=Contacts,DC=MyDomain,DC=local“)
    Dim myContact as DirectoryEntry = root.Children.Add("CN=Jane Doe", "contact")
    myContact.Properties(”givenName”).Value = “Jane”
    myContact.Properties(”sn”).Value = “Doe”
    myContact.Properties(“homePhone“).Value = “773-555-1212“
    myContact.CommitChanges()

  • System.DirectoryServices & CDOEXM

    Well, I haven't posted here recently because I've been a busy sysadmin & haven't had time to touch my copy of Visual Studio.Net. A new project, writing an Intranet for Payton's teachers and students has cropped up, and, I've been doing some new stuff.

    Namely, I've gotten to learn the joys of programming an Exchange Server with .Net. It's not what I'd call joyous with good old VB6, and it isn't any better with .Net (though System.DirectoryServices is a bit easier).

    I figure somebody else might find some of the stuff I've been up to a bit interesting/useful, so, I'm going to be posting code and explanations over the next week or so. I can't say precisely what I'm doing as this is getting syndicated on BrianDesmond.com, and, kids from Payton read there, and, whatever it is I'm working on is slated to be a surprise.

    I write all my code for Payton in VB.Net, so, that's what the samples are going to be in. I thought I'd start off with a simple one ... how to find a user with DirectorySearcher.

    There are two things that we need in order to successfully and efficiently search for our user. Number one is a search root. I keep all my user accounts under one OU in the domain, Accounts, so, that's my search root. If your accounts are under multiple OUs, you could set your search root to the domain. Lets assume they're all in/under one OU for this.

    Dim searchRoot as new DirectoryEntry(“LDAP://OU=Accounts,DC=MyDomain,DC=local“)
    Dim searcher as New DirectorySearcher(searchRoot)

    When you define an LDAP path, the thing to remember is to go from the bottom to the top (I consider the deepest OU to be the bottom, and the topmost piece to be the end of my domain name). When you define a domain, you have to do a DC= for each subdomain. This is quite a bit, so, I keep this, and a lot of other LDAP strings in the snippets section of my VS toolbox (if you weren't aware, you can drag text onto the toolbox and it will be saved as a code snippet). A side note about LDAP paths, if you need to use a comma in the name of an element (e.g. if you wanted to access container Smith, Jane), you have to escape the comma with a \, so it'd be CD=Smith\, Jane.

    Moving along, part two of using a directorysearcher object is defining an LDAP filter. LDAP Filters are actually pretty easy to write, though they take a bit of getting used to, and you have to know the names of attributes in AD (you can look up the whole AD schema in the Platform SDK). A quick explanation of how to write a filter:

    The and operator is &, the or operator is |, and the not operator is !. If you want to AND a bunch of stuff together, you do (&(criteria1)(criteria2)(criteriaN)). Likewise, to or a bunch of stuff together, you do (|(criteria1)(criteria2)(criteria3)). You can also use wildcards like *. So, let's write our filter to find a specific username:

    searcher.Filter = “(&(objectCategory=person)(sAMAccountName=brian))”

    This filter tells the DirectorySearcher to look for objects of category Person with attribute sAMAccountName=Brian (sAMAccountName is your preWin2000 logon, aka your username). The objectCategory part isn't actually necessary, but, it speeds the search up greatly, as the DirectorySearcher doesn't even touch computers or anything else other than Person objects.

    So, we've got the two major pieces done here. Just have to run the search, and do something with the result. I'm going to write the rest of the code below and explain from there:

    Dim searchRoot as new DirectoryEntry(“LDAP://OU=Accounts,DC=MyDomain,DC=local“)
    Dim searcher as New DirectorySearcher(searchRoot)
    searcher.Filter = “(&(objectCategory=person)(sAMAccountName=brian))”

    Dim result as DirectoryEntry = searcher.FindOne.GetDirectoryEntry

    So, we've not retrieved the result and stored it in a DirectoryEntry object called result. If we were looking for or could possible get more than one result, we'd use the FindAll function of DirectorySearcher, and then loop through it (the FindAll function returns a collection of type SearchResultCollection, which contains SearchResult objects). This particular query guaranetees only one result as the sAMAccountName attribute must be unique to the domain. The GetDirectoryEntry method of the SearchResult type returns the underlying DirectoryEntry representing the result.

    Now that we have a result, we can access the user's properties. Let's look up the user's first and last name:

    Dim firstName as String = CType(result.Properties(”givenName”).Value, String)
    Dim lastName as String = CType(result.Properties(”sn”).Value, String)

    The first name of a user is stored in the givenName attribute, and the lastname, or surname of a user is stored in the sn attribute. These are actually LDAP specs, AD follows them. The .Value property of a DirectoryEntry property is of type object, as there are quite a few different datatypes in AD, so you're going to need to know what you're accessing, unless you use late binding.

    That's just a simple System.DirectoryServices example. I'm sure there is someone out there that can benefit from it. Tomorrow (or next time), I'll post an example of how to create a contact object in AD. This is actually all leading up to something ... after the contact object has been created, we can setup email forwarding for a user's Exchange mailbox. I'm leading towards this, and after that, I'm not sure what is next - probably more CDO/AD, depends what I decide to write the code for next.

  • briandesmond.com

    Well, www.BrianDesmond.com is going to be down until at least Monday. The machine I use to serve it up decided not to power up after a reboot this morning. It took a little while with Dell to reach an agreement that machine would in fact not power up, rather than the monitor being bad because it wasn't getting a signal. The guy at the other end says that I need a mainboard and/or processor, so, they're shipping me both, and I'll have it Monday or Tuesday.

    Until then, no www.briandesmond.com.

  • MSDE Deployment Kit

    MS has posted an add-in for VS.Net which will allow you to package MSDE into setup & deployment projects, it appears. Here's the info on it:

    Microsoft SQL Server 2000 Desktop Engine (MSDE 2000) Deployment Toolkit (Release Candidate)

    The MSDE 2000 Deployment Toolkit (release candidate) is a plug-in to Microsoft Visual Studio that automates the process of creating an integrated package with both the application and the MSDE database.

    Source: http://www.microsoft.com/downloads/details.aspx?familyid=6e9a7403-c4ba-4d98-bb0b-2c9d6414071f

    Posted Dec 13 2003, 10:31 PM by bdesmond with 1 comment(s)
    Filed under:
  • Shortcut to Lock Computer on Win2k

    Tim posted a list of handy Windows keyboard shortcuts. Someone pointed out in his comments that some of these don't work on all versions of Windows, such as Win + L which will lock your machine on XP & 2003, but not 2000.

    Fortunately, this particular shortcut is easy enough to fix! Create a new shortcut on your desktop, hard drive, or elsewhere. Set this shortcut to run “rundll32 user32,LockWorkStation”. Once the shortcut is created, right click it, goto properties, click in the Shortcut Key text box, and press Win + L. Win + L will now lock your machine.

    EDIT: Raymond Chen tells me I shouldn't be doing this rundll32 trick. I've never had it fail on me, and I don't exactly understand what would cause it to, so all I can say, while this trick works, one of the guru's behind Windows says don't use it., so, use the LockWorkStation entrypoint at your own discretion.

  • GDN Aggregator Closing

    It look slike the Blogs.GotDotNet.com site is going to be closing up shop. All the GDN bloggers are apparently goign to be moving over to weblogs.asp.net. Now, weblogs.asp.net already has an aggregate RSS Feed, but, that's one huge RSS feed. I'd be up for aggregating all the GDN/MS bloggers on weblogs.asp.net into one feed. Interested? Let me know.

    I don't know when exactly the actual aggregator service I have running for blogs.gotdotnet.com will shutdown, I'm really waiting for activity on that site to close. When it does, I will shutdown the service.

    Vijay tells me I can aggregate any group of RSS feeds I want with the service, so, if you have a group of blogs you'd like to see in one RSS Feed, leave a comment, and we can see about getting it setup.

    Posted Dec 06 2003, 09:59 PM by bdesmond with 3 comment(s)
    Filed under:
More Posts