Link to home
Start Free TrialLog in
Avatar of itsmevic
itsmevicFlag for United States of America

asked on

ADFIND, DSQUERY or LDAP Querie for Pulling LastLogOn

Hello Experts!

    This is probably a pretty easy request as all I need to do is pull the following attributes for users/computer objects in AD:

1.)  DN Path
2.)  UserPrincipleName
3.)  DisplayName
4.)  LastLogonTimeStamp
5.)  WhenCreated

    What I have presently is great, however my problem is this when I open the .CSV because some of my OU's are thrown out of wack because there several OU layers deep, some of them 4 to 6 layers deep.  So when I look at my CSV file looking at the top level OU I'll see a few display names in the same column makes for sorting sort of difficult because there are over 70,000 rows of data.

adfind -default -bit -f "&(objectcategory=person)(objectclass=user)(!userAccountControl:AND:=2)" samaccountname userprincipalname displayname lastlogontimestamp whencreated -csv -tdca > c:\xxxx\xxxxx\LastLogonReport.csv


     In a perfect world, what I'd like to do is pull the above info in nice neat columns (so i can atleast sort them) and be able to specify how long it has been since that user has logged in. i.e. 30-60 days, 61-120 days ect, ect...didn't know if this was possible or not and then of course have the results piped out to a .CSV file.  Don't know what query language would be best i.e. ADFIND, DSQUERY or LDAP for this?

     
Avatar of Mike Kline
Mike Kline
Flag of United States of America image

You could do individual reports using adfind you would use lastlogontimetamp greater than a certain date and then less than a certain date.

...but to put it into columns like 30-60, 61-120, etc is something I don't think would be possible.

I'll add the powershell and vbscript zones too

Thanks

Mike
Avatar of itsmevic

ASKER

Thanks Mike.
Let me rephrase the question:  Just need lastlogontimestamp for all users that are not disabled.  I can get this in ADFIND or DSQUERY but due to the fact of my OU's being 5 to 6 layers deep the CSV it produces is difficult to sort.  If I could get the LDAP query for this that would be great.

I'm thinking it would go something like this, correct me if I'm wrong:

"&(objectcategory=person)(objectclass=user)(!userAccountControl=2)(lastLogonTimeStamp))"

Hmm I wish I could test this... I will in the morning. It will work, but it may not be exactly right on first pass :)

Chris
# The interval between dates. e.g. 0 to 30; 30 to 60, etc.
$DateRange = 30

# Use Quest CmdLets to get the users
Get-QADUser -Enabled -IncludedProperties lastLogonTimeStamp | %{
  # Hold onto this for convenience
  $LastLogon = $_.LastLogonTimeStamp

  # Reset the IntervalString and Multiplier values
  # Starts by looking for dates less than 30 days old, incremented by 30 on each pass of the loop
  $IntervalString = ""; $Multiplier = 1
  Do {
    # See if the logon date is after the specified date
    If ($LastLogon -gt (Get-Date).AddDays(-($DateRange * $Multiplier)) {
      # Record this value as "0 to 30", or "30 to 60", etc
      $IntervalString = "$($DateRange * ($Multiplier - 1)) to $($DateRange * $Multiplier)
    }
    # Increment the multiplier
    $Multiplier++
  # Until it has a value
  } While ($IntervalString -eq "")

  # Generate the output
  $_ | Select-Object DN, UserPrincipalName, DisplayName, LastLogonTimeStamp, WhenCreated, `
    @{n='Range';e={ $IntervalString }}
# Export it all to a CSV
} | Export-CSV "SomeFile.csv" -NoTypeInformation

Open in new window

Sure, no problem Chris, if you want to test this in the A.M. I can wait.  I'm assuming this is PowerShell correct?  I went ahead and downloaded it in preparation to test.
You can query the lastlogontimestamp in your LDAP query. It will speed things up and return fewer results (so fewer to process also). For example below if you want to find any enabled accounts which have not logged on for 45 days or more (using the Quest commandlets, this can also be done using .NET natively in PowerShell as well).

The sort is not required, because Excel or some other program can always sort the CSV columns for you, so that can be removed but I like sorting. Removing it will provide quicker results though.

The Quest AD cmdlets for PowerShell can be downloaded here: http://www.quest.com/powershell/activeroles-server.aspx.
$days = 45
$ldaptime = (Get-Date).AddDays(-$days).ToFileTimeUtc()

Get-QADUser -Enabled -sizelimit 0 -IncludedProperties lastLogonTimestamp -LdapFilter "(lastLogonTimestamp<=$($ldaptime))" | Sort lastLogonTimestamp -Descending | select Name, DN, userPrincipalName, displayName, lastLogonTimestamp, whenCreated | Export-Csv c:\temp\outfile.csv -NoTypeInformation

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Chris Dent
Chris Dent
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Jim,

Will that tool put it into columns like 30-60, 60-90, etc....

The search filter he is using in his adfind example is fine, you don't need to specify the entire useraccountcontrol string because of the -bit flag...once again nice thing Joe provided in the tool.

thanks

Mike
Thanks for the input.

I did not say is was his "perfect world" and no it will not put it in columns of 30-60 etc, but it will sort by the value.

I do believe he is using the userAccountControl to keep disabled users out of the search right?
If so, then, AFAIK, the (!(userAccountControl:1.2.840.113556.1.4.803:=2)) is correct as shown here:
http://ldapwiki.willeke.com/wiki/Filtering%20for%20Bit%20Fields
and defined here by MS:
http://support.microsoft.com/kb/269181/en-us

Thanks
-jim

Hey Jim,

You're right, it's just ADFind allows the syntax above (!userAccountControl:AND:=2) so the filter is correct as it stands as long as it's used with ADFind.

I avoided it in the PS script, replacing it with the -Enabled parameter, it'll generate the same filter as yours without anyone having to know the actual OID value :)

Chris
Quick question i'm running the ActiveRoles Management Shell for Active Directory and it's asking me a scary question (I assume this is a standard first time run notification thingy) something about Ad\Quest.ActiveRoles.ADmanagement.Types.ps1xml is published by CN="Quest Software, Inc. ", OU=R&D15, O="Quest Software, Inc.", L=somebody's name, S=California, C=US and is not trusted on your system.  Only run scripts from trusted publishers.

[V] Never run   [D] Do not run [R] Run once [A] Always run [?] help <default is "D">:  

is this a standard message?

I think it's a one time message, been a while since I installed them. Anyway, that file helps PS out so please do trust it :)

Chris
so basically Chris I'm going to copy and paste the entire code into the PS window?  

also, have you ever had an issue with copying something outside of say a command prompt window or PS window and it not pasting in?  That seems to be the case and I have "quick edit" and "insert" selected in the PS properties window.  I'm hoping to avoid having to type all of that into PS.

# Requires Quest CmdLets: http://www.quest.com/powershell/activeroles-server.aspx

# The interval between dates. Will produce these in the final column: 0 to 30; 30 to 60, etc.
$DateRange = 30

# Use Quest CmdLets to get the users
Get-QADUser -Enabled -IncludedProperties lastLogonTimeStamp -SizeLimit 0 | %{
  # Hold onto this for convenience
  $LastLogon = $_.LastLogonTimeStamp

  # Reset the IntervalString and Multiplier values
  # Starts by looking for dates less than 30 days old, incremented by 30 on each pass of the loop
  $IntervalString = ""; $Multiplier = 1

  If ($LastLogon -ne $Null) {
    Do {
      # See if the logon date is after the specified date
      If ($LastLogon -gt (Get-Date).AddDays(-($DateRange * $Multiplier))) {

        # Record this value as "0 to 30", or "30 to 60", etc
        $IntervalString = "$($DateRange * ($Multiplier - 1)) to $($DateRange * $Multiplier)"
      }

      # Increment the multiplier
      $Multiplier++

    # Until it has a value
    } While ($IntervalString -eq "")
  } Else {
    $IntervalString = "N/A"
  }

  # Generate the output
  $_ | Select-Object DN, UserPrincipalName, DisplayName, LastLogonTimeStamp, WhenCreated, `
    @{n='Range';e={ $IntervalString }}
# Export it all to a CSV
} | Export-CSV "SomeFile.csv" -NoTypeInformation

Open in new window

SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Yep I think that worked.  I had to set the execution policy but once I did that I could run the script within PS with no problems and it produces a .csv file called "somefile.csv" on the desktop which is fine because I can always rename it.  Now the hard part...so much valuable input here how to divy up the points between everyone.
Chris did the heavy lifting :)
Unfortunately, they only give 500 pts, if I had my way I'd give you all 500 pts each...If I was to chinsey in diving up the points to everyone, I do apologize.  Just know all the input you guys gave was greatly appreciated and helped immensly.
CRAP!  I mean to give Learnctx some points too for his/her effort!!! I do apologize!

I can open it up again and you can re-assign if you wish?

Chris