4

Ok. So I'm trying to find a way to avoid including ActiveDs in my project because I'm having trouble getting the dll to show up in the installer. The only reason to have it is to cast the pwdLastSet as a LongInteger.

I found an undocumented alternative. When testing it, it is either dead on or 429.49673 seconds off. I'm not sure why, does anybody have any idea? (20/49 people that i tested are 429.49673 seconds off).

UPDATE: It looks like it happens when the LowPart is negative.

Code:

    private static string DateTest() {
        return DateTest(Environment.UserName);
    }
    private static string DateTest(string userName) {
        userName = userName.Trim();
        DateTime hacked, normal;
        using (DirectorySearcher ds = new DirectorySearcher()) {
            ds.SearchScope = SearchScope.Subtree;
            ds.PropertiesToLoad.Add("distinguishedName");
            ds.PropertiesToLoad.Add("pwdLastSet");
            ds.PageSize = 1;
            ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
            ds.Filter = string.Format("(&(objectCategory=user)(sAMAccountName={0}))", userName);

            SearchResult sr = ds.FindOne();
            hacked = DateTime.FromFileTime((long)sr.Properties["pwdLastSet"][0]);

            using (DirectoryEntry user = sr.GetDirectoryEntry()) {
                var value = user.Properties["pwdLastSet"][0] as ActiveDs.LargeInteger;
                var longValue = (((long)value.HighPart) << 32) + (long)value.LowPart;
                normal = DateTime.FromFileTime(longValue);
            }
        }

        return string.Format("{3} - Difference: {0:0.0} seconds. Established Method returns: {1}. Hacked method returns: {2}",
            hacked.Subtract(normal).TotalSeconds, normal, hacked, userName);
    }
}

References:

  • Active DS Type Library
  • System.DirectoryServices
colinbashbash
  • 996
  • 2
  • 9
  • 19
  • 429 seconds over or under? And what are you comparing it to? – M.Babcock Mar 06 '12 at 22:07
  • if the LowPart is negative, then the hacked way that I'm doing it is 429.49673 seconds after the time that you get if you select it using the standard method of getting it. If the LowPart is positive, it appears that the hacked way gets the same time as the standard method. – colinbashbash Mar 06 '12 at 22:12

2 Answers2

10

You'll need to translate the AD Long Integer like this and you shouldn't need ActiveDs anymore:

long pwdLastSet = ConvertADSLargeIntegerToInt64(oUser.Properties["pwdLastSet"].Value);

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;
}
Kiquenet
  • 14,494
  • 35
  • 148
  • 243
Brett Veenstra
  • 47,674
  • 18
  • 70
  • 86
  • 1
    This didn't work. Exception is thrown on highpart. System.MissingMethodException was unhandled HResult=-2146233070 Message=Method 'System.Int64.HighPart' not found. Source=mscorlib – software is fun Sep 04 '13 at 13:12
  • @softwareisfun, maybe related: I got the same COM exception as OP from here https://stackoverflow.com/questions/8703533/what-is-this-error-system-runtime-interopservices-comexception. when I attempted to set ["pwdLastSet"] to 0 with an int64...converted the value to int32 w/ Convert.ToInt32(int64_value) and set the property value. lost 3 hours on this :p – DukeDidntNukeEm Jul 09 '21 at 21:30
  • if ***User must change password at next logon*** option is _checked_ then `LastPasswordSet` property returns `null` value ? – Kiquenet Oct 05 '22 at 10:51
5

What is wrong with this code? It should work fine:

    SearchResult sr = ds.FindOne(); 
    hacked = DateTime.FromFileTime((long)sr.Properties["pwdLastSet"][0]); 
Brian Desmond
  • 4,473
  • 1
  • 13
  • 11
  • 3
    it works. The confusion probably comes from calling Properties of `DirectoryEntry` instead of `SearchResult`. If you use `Properties["pwdLastSet"]` on `DirectoryEntry`, then you'll get InvalidCastException. – yosh Apr 07 '15 at 11:27