0

I am using the below code to get the LAPS password and expiration date for a specific computer:

string computerHostName = "hostname";
string domainController = "domain.lan";

DirectoryContext dirCtx = new DirectoryContext(DirectoryContextType.Domain, domainController);
using (Domain compsDomain = Domain.GetDomain(dirCtx))
using (DirectorySearcher adSearcher = new DirectorySearcher(compsDomain.GetDirectoryEntry()))
{
    //this is the search criteria for the domain query
    adSearcher.Filter = "(&(objectClass=computer) (cn=" + computerHostName + "))";
    adSearcher.SearchScope = SearchScope.Subtree;
    adSearcher.PropertiesToLoad.Add("ms-Mcs-AdmPwd");
    adSearcher.PropertiesToLoad.Add("ms-Mcs-AdmPwdExpirationTime");
    SearchResult searchResult = adSearcher.FindOne();
    
    //Get the LAPS password
    Console.WriteLine(searchResult.GetDirectoryEntry().Properties["ms-Mcs-AdmPwd"].Value);
    //Should get the LAPS password expiration time
    Console.WriteLine(searchResult.GetDirectoryEntry().Properties["ms-Mcs-AdmPwdExpirationTime"].Value);
}
Console.ReadLine();

However, the output looks like this:

[LAPS password here]

System.__ComObject

I have tried looking online and have already seen this question and this one but I still can't get it to work. How can I get the script to output the expiration time normally?

Any help is appreciated :)

Community
  • 1
  • 1
I.T Delinquent
  • 2,305
  • 2
  • 16
  • 33

1 Answers1

1

Hans Passant referred me to this link: How to convert Active Directory pwdLastSet to Date/Time

Instead of using:

Console.WriteLine(searchResult.GetDirectoryEntry().Properties["ms-Mcs-AdmPwdExpirationTime"].Value);

I should instead use:

Console.WriteLine((long)searchResult.Properties["ms-Mcs-AdmPwdExpirationTime"][0]);

which Correctly outputs:

132068789141660751

I.T Delinquent
  • 2,305
  • 2
  • 16
  • 33
  • 1
    The reason for this is that `DirectoryEntry.Properties` returns the value as an [`IADsLargeInteger`](https://learn.microsoft.com/en-us/windows/desktop/api/iads/nn-iads-iadslargeinteger), which you have to read using that `ConvertADSLargeIntegerToInt64` method in [the question you linked to](https://stackoverflow.com/questions/18614810/how-to-convert-active-directory-pwdlastset-to-date-time). `SearchResult.Properties` presents the value as a `long`, which you can just pass to `DateTime.FromFileTimeUtc`. I don't know why the difference. – Gabriel Luci Jun 11 '19 at 13:29
  • 1
    In this case, you should be reading from the `SearchResult` anyway, since you already asked for the value in the results (using `PropertiesToLoad`). Using `searchResult.GetDirectoryEntry().Properties` actually ends up going back out to AD and reading every attribute from the object, which is just unnecessary. – Gabriel Luci Jun 11 '19 at 13:31