About Terminal Server, Citrix, Delphi and other stuff
Last time I talked briefly about IDirectoryObject and IDirectorySearch, let’s go into a little more detail today.
IDirectoryObject is an Interface that we can use to query anything in Active Directory, users, groups, organizational units, containers and so on.
I thought the best explanation would be to build a very small sample project, so let’s do that!
First we need some units, so please add the following units to your uses clause:
Next declare the following types:
// Array of ADS_ATTR_INFO records
TAdsAttrInfoArray = array[0..ANYSIZE_ARRAY-1] of ADS_ATTR_INFO;
PAdsAttrInfoArray = ^TAdsAttrInfoArray;
Now add a Button with the name StartButton and a Memo with the name Memo1 to your form. Place the code in the OnClick handler and declare some vars:
First we will retrieve an IADs interface to a special PathName called rootDSE. rootDSE enables us to do a serverless binding to the default domain without knowing the domain name., this is perfect for our example code since you can all use it without changing the PathName.
In real life you will probably raise an exception instead of just exiting on failure…
Now we are going to read a property of rootDSE called defaultNamingContext which contains the DNS domain name (egDC=domain,DC=local):
Memo1.Lines.Add(Format(‘defaultNamingContext: %s’, [DefNamingContext]));
// We have no further use for the IADs Interface
IADsIntf := nil;
Notice that IADs.Get is declared as SafeCall so we need to wrap this in a try..except block, IADs.Get will return an EOleException in case of failure
The last step before we can obtain the IDirectoryObject Interface is to compose the PathName. I am going to work with the Administrator account as this account will probably exist in most domains. Don’t worry if you don’t have Admin privileges in your domain, any domain account can read properties.
To obtain the IDirectoryObject Interface we can use AdsGetObject but this time we use IID_IDirectoryObject:
if FAILED(hr) then
Exit;
We will now read out two attributes from the Administrator account, the username (sAMAccountName) and the description (description). Note that attribute names in Active Directory do not use CamelCase like in Delphi but Hungarian notation. Confusingly enough Microsoft refers to CamelCase as Pascal Casing and to Hungarian Notation as Camel Casing.
Although IDirectoryObject is not case sensitive I always try to keep the same case, so I use sAMAccountName and not SamAccountName when I refer to the attribute.
We are going to use the GetObjectAttributes function to read Attributes values, its first parameter is an array of AttributeNames:
The second parameter is the count of attributes, followed by a pointer to an array of ADS_ATTR_INFO records (PAdsAttrInfoArray) and the number of attributes returned:
if FAILED(hr) then
Exit;
It is important to note some things: the function can succeed but return less values than requested and the order of attributes returned is not necessarily the same as requested!
This means you should always check the pszAttrName member of the ADS_ATTR_INFO record and read the data from the pADsValues member:
When we are done we need to free the memory:
That’s it for today, you can find the sample project below. Next time I will discuss IDirectorySearch.
AdSample1 (137)Related posts:
Active Directory Altiris bug Citrix Dell Delphi Exchange Exchange2003 Exchange2010 Hewlett-Packard HP iOS Jailbreak Java LinkedIn Linux MSI MySQL Navigation Objects Office Outlook Passat PowerPoint PowerShell referall was returned RNS315 RNS510 SasLibEx script slow Terminal Server ThinApp TSAdmin TSAdminEx VBS VCDS Vista VMWare Volkswagen Windows PE WLAN Wordpress WTSWaitSystemEvent wts_event_flush
WP Cumulus Flash tag cloud by Roy Tanck requires Flash Player 9 or better.
2 Responses for "Random Active Directory Notes #3"
I have almost got this to work, but i can’t find the declaration for ADS_ATTR_INFO
Steve, it’s in the Jedi Apilib.
Leave a reply