0 votes

Hi,

Can you tell me how to look up a list of last logged-in users for computers from specific OU?

Have OU called Laptops and need to know who as last person logged into each of them?

Found that script: https://www.adaxes.com/script-repository/output-username-of-last-user-who-lgged-on-to-computer-s269.htm but it' s not design for OU

by (70 points)
0

Hello Robert,

This can be done by updating the script from our repository that you referenced. However, establishing connections to all the computers in an OU can take very long time so the script will need to be executed in a separate PowerShell instance. If this approach meets your needs, please, provide us with all the possible details regarding the desired behavior. Do you need the script to be executed on the Organizational Unit objects and output the computers and users into the Execution log? Or the report should be sent embedded into an email notification? Any additional details and live examples would be much appreciated.

0

Hi, I would prefer it sent in cvs file to a mailbox if possible. Not worried about execution time at all..

As per desired output: I would like to specify a 'Laptops' OU and script needs to look into all sub-OU's (Engineering, HR etc), read each computer account from them and display who was logged into it. As per output it's as simple as those tabs: OU - Computer name - last logged in user - time of last logging in.

Is that possible?

regards Robert

0

Hello Robert,

We recommend using an approach with a Scheduled Task and a report. The task will go through all the computers in a specific OU, check the last logged on user and save all the necessary data to Adaxes custom attributes (e.g. CustomAttribtueText1, CustomAttribtueDate1, etc.). In the Web Interface, you will use a report to output the list of computers, users that last logged on to them and other required details. Before generating the report, you will be able to select an OU where to search for computers or configure it to always generate for the very same OU. The only disadvantage of the approach is that the information in the attributes and in the report accordingly can be not up to date if a user logs on to a computer between the launches of the Scheduled Task and the report is generated. However, the approach will be much less resource consuming. Does it meet your needs?

0

Hi,

I don't plan to use it often, so manual run every now-and-then would be perfectly acceptable.

It does not needs to be overcomplicated.

regards Robert

1 Answer

+1 vote
by (270k points)

Hello Robert,

Thank you for the confirmation. Find the updated script below. To run the script, create a Custom Command configured for the Organizational Unit object type. To execute the command in Adaxes Web Interface and select the OU on which it will be run, create a Web Interface action of the Custom Command type. For details on configuring the actions, have a look at the following tutorial: https://www.adaxes.com/tutorials_WebInterfaceCustomization_ConfigureActionsPane.htm.

$win32UserFilter = "NOT SID = 'S-1-5-18' AND NOT SID = 'S-1-5-19' AND NOT SID = 'S-1-5-20'" # Exclude well-known SIDs, such as NETWORK SERVICE

function SearchObjects ($filter, $path)
{
    $searcher = $Context.BindToObject($path)
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500

    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()

        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

# Search results
$searchResults = SearchObjects "(&(objectCategory=computer)(dNSHostName=*))" $Context.TargetObject.AdsPath
$domainName = $Context.GetObjectDomain("%distinguishedName%")
$userSidsToUserName = @{}
foreach ($searchResult in $searchResults)
{
    $dNSHostName = $searchResult.Properties["dNSHostName"].Value
    if (!(Test-Connection -ComputerName $dNSHostName -Quiet -Count 1))
    {
        $Context.LogMessage("Cannot connect to computer $dNSHostName", "Warning")
        continue
    }

    # Get the last logged on user
    try
    {
        $lastUser = Get-WmiObject -Class Win32_UserProfile -ComputerName $dNSHostName -Filter $win32UserFilter -ErrorAction Stop | Sort-Object -Property @{Expression = {$_.ConvertToDateTime($_.LastUseTime)}; Descending = $True} | Select-Object -First 1
    }
    catch
    {
        $Context.LogMessage("An error occurs when getting user information from computer $dNSHostName. Error: " + $_.Exception.Message, "Warning")
        continue
    }

    # Build filter to find the user
    $userSID = $lastUser.SID
    if (!$userSidsToUserName.Contains($userSID))
    {
        $filter = [Softerra.Adaxes.Ldap.FilterBuilder]::Create("ObjectSid", $userSID)
        $userSearchResults = SearchObjects $filter "Adaxes://$domainName/rootDSE"

        if ($userSearchResults.Length -eq 0)
        {
            $Context.LogMessage("Cannot find user with SID '$userSID' for computer $dNSHostName. Probably, it is a local account.", "Warning")
            continue
        }
        $userSidsToUserName.Add($userSID, $userSearchResults[0].Properties["sAMAccountName"].Value)
    }

    # Get Username
    $username = $userSidsToUserName[$userSID]

    # Get parent name
    $computerDN = New-Object Softerra.Adaxes.Ldap.DN $searchResults[0].Properties["distinguishedName"].Value
    $parentName = $computerDN.Parent.Leaf.Value

    # Get LastUseTime
    $lastUseTime = $lastUser.ConvertToDateTime($lastUser.LastUseTime)

    # Log
    $Context.LogMessage("$parentName - $dNSHostName - $username - $lastUseTime", "Information")
}

0

Hi,

It's not exactly what I wanted due to amount of errors, but at this stage don’t think we can ask for more..

Thanks

Regards Robert

0

You could also use a logon script for the systems in scope that would update an extension attribute with the username of the user logging in every time they logged in. Then you would just need to query the extension attribute in the OU to get your list of users.

0

Hi again, Oer a year later and I have been asked to run this script twice.

Anyway - can someone tell me how to amend this script to output results into a file? Thanks :)

0

Hello Robert,

Sure, it can be done. Do you need to save the file to a share or it should be sent via email as an attachment?

0

Hi, Thanks, I think save as file on network share is perfectly enough. Regards

0

Hello Robert,

Thank you for the confirmation. Please, find the updated script below. In the script, we added the $csvFilePath variable that specified the path to the CSV file that will be created.

$win32UserFilter = "NOT SID = 'S-1-5-18' AND NOT SID = 'S-1-5-19' AND NOT SID = 'S-1-5-20'" # Exclude well-known SIDs, such as NETWORK SERVICE

# CSV File settings
$csvFilePath = '\\Server\Share\Report.csv' # TODO: modify me

function SearchObjects ($filter, $path)
{
    $searcher = $Context.BindToObject($path)
    $searcher.SearchFilter = $filter
    $searcher.SearchScope = "ADS_SCOPE_SUBTREE"
    $searcher.PageSize = 500

    try
    {
        $searchResultIterator = $searcher.ExecuteSearch()
        $searchResults = $searchResultIterator.FetchAll()

        return ,$searchResults
    }
    finally
    {
        # Release resources
        if ($searchResultIterator){ $searchResultIterator.Dispose() }
    }
}

# Search results
$searchResults = SearchObjects "(&(objectCategory=computer)(dNSHostName=*))" $Context.TargetObject.AdsPath
$domainName = $Context.GetObjectDomain("%distinguishedName%")
$userSidsToUserName = @{}
$records = New-Object System.Collections.ArrayList
foreach ($searchResult in $searchResults)
{
    $dNSHostName = $searchResult.Properties["dNSHostName"].Value
    if (!(Test-Connection -ComputerName $dNSHostName -Quiet -Count 1))
    {
        $Context.LogMessage("Cannot connect to computer $dNSHostName", "Warning")
        continue
    }

    # Get the last logged on user
    try
    {
        $lastUser = Get-WmiObject -Class Win32_UserProfile -ComputerName $dNSHostName -Filter $win32UserFilter -ErrorAction Stop | Sort-Object -Property @{Expression = {$_.ConvertToDateTime($_.LastUseTime)}; Descending = $True} | Select-Object -First 1
    }
    catch
    {
        $Context.LogMessage("An error occurs when getting user information from computer $dNSHostName. Error: " + $_.Exception.Message, "Warning")
        continue
    }

    # Build filter to find the user
    $userSID = $lastUser.SID
    if (!$userSidsToUserName.Contains($userSID))
    {
        $filter = [Softerra.Adaxes.Ldap.FilterBuilder]::Create("ObjectSid", $userSID)
        $userSearchResults = SearchObjects $filter "Adaxes://$domainName/rootDSE"

        if ($userSearchResults.Length -eq 0)
        {
            $Context.LogMessage("Cannot find user with SID '$userSID' for computer $dNSHostName. Probably, it is a local account.", "Warning")
            continue
        }
        $userSidsToUserName.Add($userSID, $userSearchResults[0].Properties["sAMAccountName"].Value)
    }

    # Get Username
    $username = $userSidsToUserName[$userSID]

    # Get parent name
    $computerDN = New-Object Softerra.Adaxes.Ldap.DN $searchResults[0].Properties["distinguishedName"].Value
    $parentName = $computerDN.Parent.Leaf.Value

    # Get LastUseTime
    $lastUseTime = $lastUser.ConvertToDateTime($lastUser.LastUseTime)

    # Log
    $Context.LogMessage("$parentName - $dNSHostName - $username - $lastUseTime", "Information")
    $recordProperties = [ordered]@{
        'Parent name' = $parentName
        'dNSHostName' = $dNSHostName
        'User name' = $username
        'lastUseTime' = $lastUseTime
    }

    $record = New-Object PSObject -Property $recordProperties
    [void]$records.Add($record)
}

# Export to CSV
$records | Export-Csv -Path $csvFilePath -NoTypeInformation

Related questions

0 votes
0 answers

It would be great if we could run a report on an OU and get the following information: Computer Name Local Accounts Whether or not the account is an administrator ... this is less important. Thanks in advance. Your support team is great and appreciated.

asked Sep 8, 2021 by mikek (80 points)
0 votes
1 answer

Hi, we currenlty have a business rule to send an email everytime the Title, Manager, Department, accountExpires, EmployeeType or FirstName attributes are ... Unit: %BusinessUnit% End Date: %accountExpires% Effective Date of Change: %adm-CustomAttributeDate2%

asked Feb 14 by KevC (60 points)
0 votes
1 answer

We have four OUs in Active Directory (Pending Deletion, Disabled with Mail Delegates, Disabled with HR Extensions and Disabled_Temp_Leave) that users are moved to prior to their eventual ... past 7 days have been moved to one of 4 of these OUs. Thanks!

asked Jun 3, 2021 by RayBilyk (230 points)
0 votes
1 answer

As part of our PCI compliance, we need to create a report of all the user accounts that are expiring in the next 30 days and email that to a user who compiles ... I was hoping to utilize Adaxes to automate it. Any assistance would be very much appreciated.

asked Apr 1, 2013 by danftasc (440 points)
0 votes
1 answer

Dear Adaxes Support, I'm trying to check the uniqueness of the Initials-proberty. My script works well so far. Import-Module Adaxes $value = $Context.GetModifiedPropertyValue("initials"); if ( ... Have you a idea how I can do this in the right way? Thanks :-)

asked Aug 13, 2013 by Napoleon (700 points)
3,326 questions
3,026 answers
7,727 comments
544,680 users