Tuesday 24 April 2007

Active directory service interface reference

I needed to retrive some values from Ldap and for some properties I was not able to retrieve its value. I used standard classes from namespace System.DirectoryServices and always got System.Runtime.InteropServices.COMException(0x8000500c). After some investigation I found that for access to Ldap I can use ADSI interface. I found that the property I wanted to get was of octet string datatype. Unfortunatelly I did not managed to find how to retrieve valuo of the property though PropertyCollection. I was able to find that the collection contains the property, but I could not read its value.

At first I used something like that:

// works almost for everything, but not for octet strings (array of bytes)
// properties is of type PropertyCollection from System.DirectoryServices
string value = string.Empty;

if (properties.Contains(key))
{
value = properties[key].Value.ToString();
}


Solution of the problem:

string value = string.Empty;

try
{
// if the item do not exists exception is thrown
ActiveDs.IADsPropertyEntry entry = ActiveDs.IADsPropertyEntry)propertyList.Item(key);

// get types
int propertyType = entry.ADsType;
int valueType = (ActiveDs.IADsPropertyValue)((object[])((ActiveDs.IADsPropertyEntry)propertyList.GetPropertyItem(key, propertyType)).Values)[0]).ADsType;

switch (valueType)
{
// for octet string (array of bytes) we have to create string
case (int)ActiveDs.ADSTYPEENUM.ADSTYPE_OCTET_STRING:
value = Sstem.Text.Encoding.ASCII.GetString((byte[])((ActiveDs.IADsPropertyValue)((object[])((ActiveDs.IADsPropertyEntry)propertyList.GetPropertyItem(key, propertyType)).Values)[0]).OctetString);
break;

// for all others - all current properties are of this type
case (int)ActiveDs.ADSTYPEENUM.ADSTYPE_CASE_IGNORE_STRING:
value = ((ActiveDs.IADsPropertyValue)((object[])((ActiveDs.IADsPropertyEntry)propertyList.GetPropertyItem(key, propertyType)).Values)[0]).CaseIgnoreString;
break;
// in other cases you can add new section
}
catch (System.Runtime.InteropServices.COMException cex)
{
if (cex.ErrorCode == -2147463155)
Trace.Write(cex);
else throw;
}


In this case you have to add to your references Activeds.dll.

Thursday 19 April 2007

How to use generic ForEach method

You can see in the example how you can use generic ForEach method.

DateTime latestDate = DateTime.MinValue;
string version = string.Empty;

list.ForEach(delegate(Version v)
{
if (v.CreatedAt > latestDate)
{
latestDate = v.CreatedAt;
version = v.Number;
});