views:

639

answers:

2

I'm trying to get the Int64 value of a Directory Services object's "uSNChanged" value. Unfortunately, it is always coming back as a COM object of some kind. I've tried using casting to Int64, calling Int64.Parse(), and calling Convert.ToInt64(). None of these work.

For a given DirectoryEntry object, this code will display the properties:

 private static void DisplaySelectedProperties(DirectoryEntry objADObject)
 {
  try
  {
   string[] properties = new string[] {
    "displayName",
    "whenCreated",
    "whenChanged",
    "uSNCreated",
    "uSNChanged",
   };

   Console.WriteLine(String.Format("Displaying selected properties of {0}", objADObject.Path));
   foreach (string strAttrName in properties)
   {
    foreach (var objAttrValue in objADObject.Properties[strAttrName])
    {
     string strAttrValue = objAttrValue.ToString();
     Console.WriteLine(String.Format("   {0, -22} : {1}", strAttrName, strAttrValue));
    }
   }
   Console.WriteLine();
  }
  catch (Exception ex)
  {
   throw new ApplicationException(string.Format("Fatal error accessing: {0} - {1}", objADObject.Path, ex.Message), ex);
  }
 }

This is the output:

Displaying selected properties of LDAP://server/o=org/cn=obj
   displayName            : Display Name
   whenCreated            : 7/8/2009 7:29:02 PM
   whenChanged            : 7/8/2009 10:42:23 PM
   uSNCreated             : System.__ComObject
   uSNChanged             : System.__ComObject

How do I convert that System.__ComObject into a Int64?


Solution Used:

This is the solution I used based on marc_s's solution below:

 public static Int64 ConvertADSLargeIntegerToInt64(object adsLargeInteger)
 {
   var highPart = (Int32)adsLargeInteger.GetType().InvokeMember("HighPart", System.Reflection.BindingFlags.GetProperty, null, adsLargeInteger, null);
   var lowPart  = (Int32)adsLargeInteger.GetType().InvokeMember("LowPart",  System.Reflection.BindingFlags.GetProperty, null, adsLargeInteger, null);
   return highPart * ((Int64)UInt32.MaxValue + 1) + lowPart;
 }
+2  A: 

It looks like it's an IADsLargeInteger type, so a little interop magic will be required to extract the values. This Thread contains a sample VB implementation -- and mentions problems similar to your own -- however I'm nowhere near able to verify the usefulness of it right now. Hope this helps.

Tom
Thanks for the answer. You too are correct, but I flagged Marc's answer as correct since he actually provided a source snippet.
Simon Gillbee
+3  A: 

I'm using this snippet of code in my ADSI Browser BeaverTail which is written in C#:

Int64 iLargeInt = 0;

IADsLargeInteger int64Val = (IADsLargeInteger)oPropValue.LargeInteger;
iLargeInt = int64Val.HighPart * 4294967296 + int64Val.LowPart;

As far as I can tell, this should work just fine.

Marc

marc_s
For people wanting to use this solution, you will need to include a COM reference to ActiveDs in your project because IADsLargeInteger is not a native .NET interface. This works great! For my solution, I didn't want to introduce the ActiveDs reference so I did a similar solution but used some reflection magic. See my edited question for the solution I settled upon
Simon Gillbee