• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1166
  • Last Modified:

Finding the lastest logon time

Hi Experts,

I have 3 domain controllers on my environment they replicate with eachother as you all know, I am trying to get the lastlogon time of every user in my environment, keep in mind that these users do not hit a domain controller they could hit DC1, DC2 or DC3 as they logon, so I found a solution on line that is suppose to help me:

http://dmitrysotnikov.wordpress.com/2008/07/18/finding-the-latest-logon-time/#comment-7029

This solutions uses the ActiveRoles Management Shell from Quest and when I attempt to execute the script I get no results, here is the script:

Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName username).LastLogon
} | Measure-Latest

Measure-Lastest is a function that Dmitry created and can be found here:

http://dmitrysotnikov.wordpress.com/2008/07/16/measure-latest-finding-the-latest-date-time/

# get a set of DateTime values from the pipeline
# filter out $nulls and produce the latest of them
# (c) Dmitry Sotnikov
function Measure-Latest {
    BEGIN { $latest = $null }
    PROCESS {
            if (($_ -ne $null) -and (($latest -eq $null) -or ($_ -gt $latest))) {
                $latest = $_
            }
    }
    END { $latest }
}

So in order to run this I have to follow the directions on the link listed above, but the easiest way to run the script is by creating a script for the measure-lastest.ps1 and another one with this:

. c:\scripts\measure-latest.ps1
Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName username).LastLogon.Value
} | Measure-Latest

and save the script as whatever.PS1, but again, somehow I am unable to obtain any display results on my screen, I run it and nothing happens.
0
Islandr
Asked:
Islandr
  • 8
  • 7
  • 5
  • +1
2 Solutions
 
BxozCommented:
Hello,

Do you realy need to use Powershell
Because you can dou a simple search
Ad Search
0
 
Mike KlineCommented:
I'll let some of the powershell guys answer this one,  you could pull the lastlogontimestamp attribute too  

http://blogs.technet.com/b/askds/archive/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works.aspx

...not as accurate lastlogon but it does replicate.

Thanks

Mike
0
 
BxozCommented:
I think you can find you answer here

http://www.rlmueller.net/Last%20Logon.htm
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
QlemoC++ DeveloperCommented:
The culprit is
 (Get-QADUser ....).LastLogon.Value
because there is no property called Value for LastLogon. Just omit that (.Value), and it should work.
Of course you need to replace  username  by something existing.

If you want to get errors for uninitialized vars and non-existent properties and methods, use
  set-strictmode -Version 2.0
0
 
BxozCommented:
A PowerShell script has also been developed to query all Domain Controllers in the domain for the largest (latest) value of the lastLogon attribute for each user in the domain. This program uses the DirectoryServices.DirectorySearcher object. The last logon dates for each user are converted into local time. The times are adjusted for daylight savings time, so they may differ from the values reported by the LastLogon.vbs program by one hour. This program works in PowerShell V1 and V2.

# PSLastLogon.ps1
# PowerShell script to determine when each user in the domain last
# logged on.
#
# ----------------------------------------------------------------------
# Copyright (c) 2011 Richard L. Mueller
# Hilltop Lab web site - http://www.rlmueller.net
# Version 1.0 - March 16, 2011
#
# This program queries every Domain Controller in the domain to find the
# largest (latest) value of the lastLogon attribute for each user. The
# last logon dates for each user are converted into local time. The
# times are adjusted for daylight savings time, as presently configured.
#
# You have a royalty-free right to use, modify, reproduce, and
# distribute this script file in any way you find useful, provided that
# you agree that the copyright owner above has no warranty, obligations,
# or liability for such use.

Trap {"Error: $_"; Break;}

$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Domain = [ADSI]"LDAP://$D"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.PageSize = 200
$Searcher.SearchScope = "subtree"

$Searcher.Filter = "(&(objectCategory=person)(objectClass=user))"
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
$Searcher.PropertiesToLoad.Add("lastLogon") > $Null

# Create hash table of users and their last logon dates.
$arrUsers = @{}

# Enumerate all Domain Controllers.
ForEach ($DC In $D.DomainControllers)
{
    $Server = $DC.Name
    $Searcher.SearchRoot = "LDAP://$Server/" + $Domain.distinguishedName
    $Results = $Searcher.FindAll()
    ForEach ($Result In $Results)
    {
        $DN = $Result.Properties.Item("distinguishedName")
        $LL = $Result.Properties.Item("lastLogon")
        If ($LL.Count -eq 0)
        {
            $Last = [DateTime]0
        }
        Else
        {
            $Last = [DateTime]$LL.Item(0)
        }
        If ($Last -eq 0)
        {
            $LastLogon = $Last.AddYears(1600)
        }
        Else
        {
            $LastLogon = $Last.AddYears(1600).ToLocalTime()
        }
        If ($arrUsers.ContainsKey("$DN"))
        {
            If ($LastLogon -gt $arrUsers["$DN"])
            {
                $arrUsers["$DN"] = $LastLogon
            }
        }
        Else
        {
            $arrUsers.Add("$DN", $LastLogon)
        }
    }
}

# Output latest last logon date for each user.
$Users = $arrUsers.Keys
ForEach ($DN In $Users)
{
    $Date = $arrUsers["$DN"]
    "$DN;$Date"
}

Open in new window

0
 
IslandrAuthor Commented:
Bxoz,

You script worked, however the Output is not that user friendly,  I would like to have something like:

Lastname            Firstname               Username                    Lastlogontime

Smith                   Joe                          Joe.Smith                    8/8/2011 10:34:50 PM

Qlemo,

When executing the script based on your suggestions I got the same resulst:

Nothing is happening, here is a copy of the script:

. c:\scripts\measure-latest.ps1
Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName logonname).LastLogon
} | Measure-Latest

I look forward to hear from you all.

Thanks,

0
 
QlemoC++ DeveloperCommented:
What is "logonname"? Do you want to have the login time of all users listed? That wouldn't work that way, and require much more effort. Where "Logonname" is placed, you need to put a real username in.
0
 
BxozCommented:
Yes you've right try this one
PSLastLogon.ps1 > PSLastLogon.csv

CSV Works !

# PSLastLogon.ps1
# PowerShell script to determine when each user in the domain last
# logged on.
#
# ----------------------------------------------------------------------
# Copyright (c) 2011 Richard L. Mueller
# Hilltop Lab web site - http://www.rlmueller.net
# Version 1.0 - March 16, 2011
#
# This program queries every Domain Controller in the domain to find the
# largest (latest) value of the lastLogon attribute for each user. The
# last logon dates for each user are converted into local time. The
# times are adjusted for daylight savings time, as presently configured.
#
# You have a royalty-free right to use, modify, reproduce, and
# distribute this script file in any way you find useful, provided that
# you agree that the copyright owner above has no warranty, obligations,
# or liability for such use.

Trap {"Error: $_"; Break;}

$D = [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
$Domain = [ADSI]"LDAP://$D"
$Searcher = New-Object System.DirectoryServices.DirectorySearcher
$Searcher.PageSize = 200
$Searcher.SearchScope = "subtree"

$Searcher.Filter = "(&(objectCategory=person)(objectClass=user))"
$Searcher.PropertiesToLoad.Add("distinguishedName") > $Null
$Searcher.PropertiesToLoad.Add("lastLogon") > $Null

# Create hash table of users and their last logon dates.
$arrUsers = @{}

# Enumerate all Domain Controllers.
ForEach ($DC In $D.DomainControllers)
{
    $Server = $DC.Name
    $Searcher.SearchRoot = "LDAP://$Server/" + $Domain.distinguishedName
    $Results = $Searcher.FindAll()
    ForEach ($Result In $Results)
    {
        $DN = $Result.Properties.Item("distinguishedName")
        $LL = $Result.Properties.Item("lastLogon")
        If ($LL.Count -eq 0)
        {
            $Last = [DateTime]0
        }
        Else
        {
            $Last = [DateTime]$LL.Item(0)
        }
        If ($Last -eq 0)
        {
            $LastLogon = $Last.AddYears(1600)
        }
        Else
        {
            $LastLogon = $Last.AddYears(1600).ToLocalTime()
        }
        If ($arrUsers.ContainsKey("$DN"))
        {
            If ($LastLogon -gt $arrUsers["$DN"])
            {
                $arrUsers["$DN"] = $LastLogon
            }
        }
        Else
        {
            $arrUsers.Add("$DN", $LastLogon)
        }
    }
}

# Output latest last logon date for each user.
$Users = $arrUsers.Keys
ForEach ($DN In $Users)
{
    $Date = $arrUsers["$DN"]
    "$DN	$Date"
}

Open in new window

0
 
IslandrAuthor Commented:
Qlemo,

This is what I ran and it worked:

. c:\scripts\measure-latest.ps1
Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName Joe_Smith).LastLogon
} | Measure-Latest | format-table

Now, How do I run this to query all users in my AD? instead just one, I know that I can accomplish this by executing the following:

Get-QADUser -sizelimit 0 | select lastname,firstname,logonname,lastlogon | sort {$_.lastlogon.value.ticks} |  convertto-html > test.htm

But the problem is that this just get the results from maybe one domain and do not get the realtime replication between domains and we have 3, please let me know if there is a way that I can get results like:

Lastname            Firstname               Username                    Lastlogontime

Smith                   Joe                          Joe.Smith                    8/8/2011 10:34:50 PM

Using the above script for all users:

. c:\scripts\measure-latest.ps1
Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName Joe_Smith).LastLogon
} | Measure-Latest | format-table


Thanks,
0
 
IslandrAuthor Commented:
Bxoz,

It did not sepate the fields, it's the same output as if I had run the script on the CLI, I know that format-table function can do this, but I do not know where to place it.

Thanks,
0
 
BxozCommented:
I don't know if you have take the last code but I have change the last line in the code

 "$DN      $Date"

instated of

"$DN;$Date"

It work better with CSV i don't know either for format-table
0
 
QlemoC++ DeveloperCommented:
Islandr,

Do you want to follow both approaches, or concentrate on one? The "manual" approach presented by Bxoz is good if you want to keep off the QAD cmdlets, or want to learn more about the internal processing. The QAD tools however make it more easy to access AD components.
0
 
IslandrAuthor Commented:
Qlemo,

I would like to use the two methods, because we need to compare the two reports, so if you can help me with this:

 c:\scripts\measure-latest.ps1
Get-QADComputer -ComputerRole DomainController | foreach {
(Get-QADUser -Service $_.Name -SamAccountName logonname).LastLogon
} | Measure-Latest

But query all users, I would greatly appreciated.

Thanks,
0
 
QlemoC++ DeveloperCommented:
Well, we need a reasonable concatenation / looping then:
function Measure-Latest {
    BEGIN { $latest = $null }
    PROCESS {
            if (($_ -ne $null) -and (($latest -eq $null) -or ($_ -gt $latest))) {
                $latest = $_
            }
    }
    END { $latest }
}

Set-StrictMode -Version latest
Get-QADComputer -ComputerRole DomainController `
| % { Get-QADUser -Service $_.Name  } `
| select name, lastlogon `
| group name `
| % {
  $_ | Add-Member NoteProperty -Name LastLogon -Value ($_.group | % { $_.LastLogon } | ? {$_ -ne $null} | Measure-Latest)
  $_ | select Name, LastLogon
}

Open in new window

In the end this will result in a list of objects consisting of a single name and the latest login time. Since those are still objects, you can process them further, for example with format-list or format-table -autosize. Instead of including the code of measure-latest you can include the script as you have done already, of course.
0
 
IslandrAuthor Commented:
Qlemo,

I am getting:

WARNING: This search was configured to retrieve only the first 1000 results. To retrieve more results, increase the size limit using the -SizeLimit parameter or set the default size limit using Set-QADPSSnapinSettings with the -DefaultSizeLimit parameter. Use 0 as the value of size limit to retrieve all possible search results.

So, I know that if I do -SizeLimit 0 the script will query all user with no limit.  The question is where may I place the -SizeLimit 0 parameter?

Thanks,

0
 
QlemoC++ DeveloperCommented:
You will set that with Get-QADUser in line 13:
 % { Get-QADUser -Service $_.Name  -SizeLimit 0 } `

Open in new window

0
 
IslandrAuthor Commented:
Qlemo,

I am still getting the WARNING message.  Any ideas?
0
 
QlemoC++ DeveloperCommented:
Nope.
0
 
IslandrAuthor Commented:
Qlemo,

Alright, I think that I found what was the problem with the WARNING.  Somehow the script was caching into the ActiveRoles Management Shell Console and then I was keep getting the warning message after saved the script, so I closed and open another windows console and it ran without issues.

May I split the points between you and Bxoz? I am going to use the two solutions.
0
 
QlemoC++ DeveloperCommented:
No issues with a split.
0
 
IslandrAuthor Commented:
Qlemo and Bxoz they were in the top, thank you guys for your assistance, I am a newbie in PS, I think that I have a long way to go.

Again, Thanks,
0

Featured Post

Configuration Guide and Best Practices

Read the guide to learn how to orchestrate Data ONTAP, create application-consistent backups and enable fast recovery from NetApp storage snapshots. Version 9.5 also contains performance and scalability enhancements to meet the needs of the largest enterprise environments.

  • 8
  • 7
  • 5
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now