How to narrow retrieve the most current last logon user

This topic contains 8 replies, has 3 voices, and was last updated by Profile photo of I Am Sir Ask Alot I Am Sir Ask Alot 5 months, 1 week ago.

  • Author
    Posts
  • #45074
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    I am using the following code and it works great to retrieve users that have profiles on a system and then uses Get-WinEvent and looks for only 4642 events that user has created and then it uses Get-ADUser to see if that user is in Active Directory, so it filters out any locally created custom account.

    The problem with this script is that it gets multiple users and all I want is for it to retrieve the most current last logged on user from the list of users the Get-WmiObject Win32_UserProfile -ComputerName $Computer -Filter 'Special=False').LocalPath -replace 'C:\\users\\'," gets.

    I have no idea how to go about doing this and any help here would be MUCH appreciated.

    Thank you all

    Here is the code:

    $Computers = 'Computer1', 'Computer2', 'Computer3'
    
    Foreach ($Computer in $Computers)
    {   
        $Users = (Get-WmiObject Win32_UserProfile -ComputerName $Computer -Filter 'Special=False').LocalPath -replace 'C:\\users\\','' 
    
        $ADComputerProps = Get-ADComputer -Identity $Computer -Properties * -ErrorAction SilentlyContinue
    
        Foreach ($User in $Users)
        {
            $UserLastLogonEvent = Get-WinEvent -Computer $Computer -FilterHashtable @{Logname='Security';ID='4624';Data=$User;} -MaxEvents 1 -ErrorAction SilentlyContinue
                    
            If ($UserLastLogonEvent)
            {
                $SID = '{0}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value 
    
                $User = '{1}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value
    
                $Domain = '{2}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value
    
                $ADUserProps = Get-ADUser -Identity $User -Properties * -ErrorAction SilentlyContinue
    
                If ($ADComputerProps) 
                {
                    If ($ADUserProps)
                    {
                        [pscustomobject]@{
                
                            'ComputerDistinguishedName' = $ADComputerProps.DistinguishedName
                            'ComputerName' = $Computer
                            'ComputerIPV4Address' = $ADComputerProps.IPv4Address
                            'ComputerLastADLogonDate' = $ADComputerProps.LastLogonDate
                            'ComputerOperatingSystem' = $ADComputerProps.OperatingSystem
                            'ComputerServerReferenceBL' = $ADComputerProps.serverReferenceBL 
                            'UserDomain' = $Domain
                            'UserDisplayName' = $ADUserProps.DisplayName
                            'UserDepartment' = $ADUserProps.Department
                            'UserDescription' = $ADUserProps.Description
                            'UserEmailAddress' = $ADUserProps.EmailAddress
                            'UserLastADLogonDate' = $ADUserProps.LastLogonDate
                            'UserLastComputerLogOnDate' = $UserLastLogonEvent.TimeCreated
                            'UserLastLoggedOn' = $User
                            'UserName' = $ADUserProps.Name
                            'UserOffice' = $ADUserProps.Office
                            'UserOfficePhone' = $ADUserProps.OfficePhone
                            'UsewrOrganization' = $ADUserProps.Organization
                            'UserSamAccountName' = $ADUserProps.SamAccountName
                            'UserSID' = $SID
                        }
                    }
                }
            }
        }
    }
  • #45082
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    If you look at all of the properties of the Win32_UserProfile class, you'll see there is a property LastUseTime. This datetime value is stored as WMI datetime, which appears to be sortable. If we get the profile data, sort it descending on the LastUseTime property and then Select -First 1, we should get the last user that logged in, something like this:

    Get-WmiObject Win32_UserProfile -Filter "Special=False" | 
    Sort-Object -Property LastUseTime -Descending |
    Select LocalPath, LastUseTime, @{Name="Test";Expression={[System.Management.ManagementDateTimeConverter]::ToDateTime($_.LastUseTime)}} -First 1
    
  • #45190
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    Thanks, but the only problem with relying on the LastUseTime is that it can be a task ran within the context of the user and what I want is the actual logon time, which is why I was using Event ID 4624 and filtering out special logons. Basically any event that takes place that was created under a user account will run and that will force the NTUser.dat file to be written to which will be recorded as the LastUseTime and that is not exactly what I am looking for.

    I could be completely wrong about this, but I have researched fairly thoroughly and this is the conclusion that I have come to.

  • #45217
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    Using the code you've already got, just collect your events up into a variable, sort the events by your time (descending), then select the first event. I would probably turn this into an advanced function to use the pscustom object with the pipeline, but this is functional.

    $Computers = 'Computer1', 'Computer2', 'Computer3'
    
    Foreach ($Computer in $Computers)
    {   
        $Users = (Get-WmiObject Win32_UserProfile -ComputerName $Computer -Filter 'Special=False').LocalPath -replace 'C:\\users\\','' 
    
        $ADComputerProps = Get-ADComputer -Identity $Computer -Properties * -ErrorAction SilentlyContinue
    
        Foreach ($User in $Users)
        {
            $UserLastLogonEvent = Get-WinEvent -Computer $Computer -FilterHashtable @{Logname='Security';ID='4624';Data=$User;} -MaxEvents 1 -ErrorAction SilentlyContinue
                    
            If ($UserLastLogonEvent)
            {
                $SID = '{0}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value 
    
                $User = '{1}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value
    
                $Domain = '{2}' -f $UserLastLogonEvent.Properties[4].Value,$UserLastLogonEvent.Properties[5].Value,$UserLastLogonEvent.Properties[6].Value
    
                $ADUserProps = Get-ADUser -Identity $User -Properties * -ErrorAction SilentlyContinue
    
                If ($ADComputerProps) 
                {
                    If ($ADUserProps)
                    {
                        $colevents += @([pscustomobject]@{
                
                            'ComputerDistinguishedName' = $ADComputerProps.DistinguishedName
                            'ComputerName' = $Computer
                            'ComputerIPV4Address' = $ADComputerProps.IPv4Address
                            'ComputerLastADLogonDate' = $ADComputerProps.LastLogonDate
                            'ComputerOperatingSystem' = $ADComputerProps.OperatingSystem
                            'ComputerServerReferenceBL' = $ADComputerProps.serverReferenceBL 
                            'UserDomain' = $Domain
                            'UserDisplayName' = $ADUserProps.DisplayName
                            'UserDepartment' = $ADUserProps.Department
                            'UserDescription' = $ADUserProps.Description
                            'UserEmailAddress' = $ADUserProps.EmailAddress
                            'UserLastADLogonDate' = $ADUserProps.LastLogonDate
                            'UserLastComputerLogOnDate' = $UserLastLogonEvent.TimeCreated
                            'UserLastLoggedOn' = $User
                            'UserName' = $ADUserProps.Name
                            'UserOffice' = $ADUserProps.Office
                            'UserOfficePhone' = $ADUserProps.OfficePhone
                            'UsewrOrganization' = $ADUserProps.Organization
                            'UserSamAccountName' = $ADUserProps.SamAccountName
                            'UserSID' = $SID
                        })
                    }
                }
            }
        }
    }
    
    $colevents | Sort-Object UserLastComputerLogOnDate -Descending | Select-Object -First 1
    Remove-Variable colevents
    
    • This reply was modified 5 months, 1 week ago by Profile photo of Curtis Smith Curtis Smith.
  • #45220
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    CURTIS!!

    That did it.

    I could kiss that beautiful bald head of yours.

    Actually, this code was just a snippet of a much larger script that is already an advanced function.

    Thanks a bunch man, I love you.

  • #45222
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    BTW, is there a reason to remove the ColEvents variable at the end there, or is that just some common practice that you like to do?

    Thanks

  • #45224
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    GOD I LOVE PowerShell.org!!

    You guys are a life saver man.

  • #45269
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    The remove is there because when I was testing the script I initially just added the PSCustomObject to the variable without enclosing it in an array first.

    IE.

    $colevents += [pscustomobject]@{
                
                            'ComputerDistinguishedName' = $ADComputerProps.DistinguishedName
                            'ComputerName' = $Computer
                            'ComputerIPV4Address' = $ADComputerProps.IPv4Address
                            etc. etc. etc.
    }
    

    This created $colevents as an object type variable rather than an array, which also meant that it only had the last event found, not the whole collection. Since I was using the ISE, the $colevents stayed around between runs. When I enclosed the [pscustomobject] in and array @(), the same result happened because the variable $colevents had already been created as an object. I added remove-variable so that it would be unset at the end and then recreated on the next run.

    Technically it is not required since running in a console, rather than ISE would terminate the variables at the end of the run, but in programming it is good practice to clean up your variables when you no longer need their value so that subsequent uses of the variable name or new data assignment does not contain unexpected results. Happens with loops a lot. But anyway, that's why it's there. You can remove it if you like.

  • #45301
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    Great info!

    Thanks again man.

    Appreciate your help.

You must be logged in to reply to this topic.