How to list all computers and the last time they were logged onto in AD?

心不动则不痛 提交于 2019-12-04 14:03:43

问题


I am trying to retrieve a list of Computer Names and the date they were last logged onto from Active Directory and return them in a datatable. Getting the names is easy enough but when I try to add the "lastLogon" or "lastLogonTimestamp" like shown below, the only values I get for the lastLogonTimestamp is "System._ComObject"

public DataTable GetListOfComputers(string domainName)
{
  DirectoryEntry entry = new DirectoryEntry("LDAP://DC=" + domainName + ",DC=com");
  DirectorySearcher search = new DirectorySearcher(entry);
  string query = "(objectclass=computer)";
  search.Filter = query;

  search.PropertiesToLoad.Add("name");
  search.PropertiesToLoad.Add("lastLogonTimestamp");

  SearchResultCollection mySearchResultColl = search.FindAll();

  DataTable results = new DataTable();
  results.Columns.Add("name");
  results.Columns.Add("lastLogonTimestamp");

  foreach (SearchResult sr in mySearchResultColl)
  {
    DataRow dr = results.NewRow();
    DirectoryEntry de = sr.GetDirectoryEntry();
    dr["name"] = de.Properties["Name"].Value;
    dr["lastLogonTimestamp"] = de.Properties["lastLogonTimestamp"].Value;
    results.Rows.Add(dr);
    de.Close();
  }

  return results;
}

If I query AD using a tool like LDP I can see that the property exists and is populated with data. How can I get at this info?


回答1:


It'd be easier to use the ComputerPrincipal class and a PrincipalSearcher from System.DirectoryServices.AccountManagement.

PrincipalContext pc = new PrincipalContext(ContextType.Domain, domainName);
PrincipalSearcher ps = new PrincipalSearcher(new ComputerPrincipal(pc));
PrincipalSearchResult<Principal> psr = ps.FindAll();
foreach (ComputerPrincipal cp in psr)
{
    DataRow dr = results.NewRow();
    dr["name"] = cp.Name;
    dr["lastLogonTimestamp"] = cp.LastLogon;    
    results.Rows.Add(dr);
}



回答2:


**The way to treat the property 'lastLogonTimestamp' retrieved from a DirectoryEntry is to convert it to IADSLargeInteger

from: http://www.dotnet247.com/247reference/msgs/31/159934.aspx**

The __ComObject returned for these types is IADsLargeInteger for the numeric values, and IADsSecurityDescriptor for SecurityDescriptors.

You can include a reference on the COM tab to Active DS Type Lib and get the definition for these interfaces or manually define them. Here is a sample:

using System;
using System.DirectoryServices;
using System.Runtime.InteropServices;

//This is the managed definition of this interface also found in
ActiveDs.tlb
[ComImport]
[Guid("9068270B-0939-11D1-8BE1-00C04FD8D503")]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
internal interface IADsLargeInteger
{
    [DispId(0x00000002)]
    int HighPart{get; set;}
    [DispId(0x00000003)]
    int LowPart{get; set;}
}

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        DirectoryEntry entry = new
DirectoryEntry("LDAP://cn=user,cn=users,dc=domain,dc=com");
        if(entry.Properties.Contains("lastLogon"))
        {
            IADsLargeInteger li =
(IADsLargeInteger)entry.Properties["lastLogon"][0];    
            long date = (long)li.HighPart << 32 | (uint)li.LowPart;
            DateTime time = DateTime.FromFileTime(date);
            Console.WriteLine("Last logged on at: {0}", time);
        }
    }

}

David Stucki Microsoft Developer Support




回答3:


Try using IADsLargeInteger (Source)

DirectoryEntry user = DirectoryEntry("LDAP://" + strDN);
if (user.Properties.Contains("lastlogontimestamp"))
{
  // lastlogontimestamp is a IADsLargeInteger
  IADsLargeInteger li = (IADsLargeInteger) 
  user.Properties["lastlogontimestamp"][0];
  long lastlogonts = 
      (long)li.HighPart << 32 | (uint)li.LowPart;
  user.Close();
  return DateTime.FromFileTime(lastlogonts);
}



回答4:


A simple answer to the original question is to access the property on your search result:

sr.Properties["lastLogonTimestamp"][0].ToString()

DateTime.FromFileTimeUTC(long.Parse(sr.Properties["lastLogonTimestamp"][0].ToString())) to obtain a datetime value

I'm having a similar issue, I can access the lastLogonTimestamp property in the SearchResult and obtain a value in the indexed result but after using SearchResult.GetDirectoryEntry() I am not able to access a valid result for the lastLogonTimestamp property on the DirectoryEntry.

Has anyone else run into this issue with the DirectoryEntry returned from SearchResult.GetDirectoryEntry() as it relates to access to the lastLogonTimestamp property?



来源:https://stackoverflow.com/questions/1602036/how-to-list-all-computers-and-the-last-time-they-were-logged-onto-in-ad

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!