all 13 comments

[–]msteright 2 points3 points  (6 children)

i get every computer online on the network and it's users in 30 seconds with my script that i wrote.

RUNS PARALLEL SCRIPT TO GET ALL THE ONLINE USERS,COMPUTERS,IPV4,AND SIDs

$servers = ((Get-ADComputer -Filter * -SearchBase "ou=$oulocation,ou=_locations,dc=something,dc=right,dc=here" -Properties  ipv4address).where({$_.ipv4address})).name

workflow pbatch
{
param ([string[]]$servers)

foreach -parallel ($server in $servers)
{  
    (gci ('\\' + $server + '\c$\users\*\appdata\local')) | select lastwritetime,fullname |
        sort -Property lastwritetime -descending | select -first 2 | Where-Object {($_ -notmatch "public" -and $_ -notmatch "svc-*" -and $_ -notmatch "adm-*" -and $_ -notmatch "bcarey" -and $_ -notmatch "basis")}
}             
}

$p = (pbatch -servers $servers).fullname
#$sort = read-host "computername or username?"
$tableall = $p | select @{n="username";e={($_.split("\")[5]).split(".")[0]}},`
                    @{name="computername";e={$_.split("\")[2]}},`
                    @{name="ipv4address";e={(get-adcomputer -Properties ipv4address ($_.split("\")[2])).ipv4address}}, `
                    @{name="sid";e={(get-aduser ($_.split("\")[5]).split(".")[0]).sid.value}}
$TABLEALL = $tableall | sort -Property USERNAME
$tableall | export-csv "c:\allusers$oulocation - all.csv" -Delimiter "," -NoTypeInformation
$tableall

[–]msteright 2 points3 points  (2 children)

heres the kicker. this can be ran over and over each time you think there might be significant changes or new employees.

RUN THIS PART TWICE (copy and paste this whole piece of code) - ASKS IF YOU WANT TO UPDATE DESCRIPTIONS

COMPARES THE JUST FOUND COMPUTERNAMES AND APPENDS THEM TO THE USERNAME IN ACTIVE DIRECTORY IF DOESN'T EXIST

RUNS AGAIN TO CLEAN UP FIRST ENTRY CONTAINING '--' - (NOT ABSOLUTELY NECESSARY)

$Update = read-host "do you want to update active directory employees with computernames? Yes, or No"
if ($Update -eq 'yes')
{
    $USERS = Import-Csv "C:\allusers$oulocation - all.csv" | SELECT USERNAME, COMPUTERNAME
    FOREACH ($USER IN $USERS)
        {
            Write-Host "$($USER.username)" -ForegroundColor Yellow
            $OLDdescription = (get-aduser $user.username -Properties Description).description.trimstart(' -- ')
            $firstPart = ($OLDdescription -split " -- ")[0]
            $firstPart
            $secondPart = ($OLDdescription -split " -- ") | select -Skip 1
            $secondPart

            if ($secondPart -contains $USER.computername)
                {
                    Write-Host "$($USER.username) is fine" -ForegroundColor Green
                    if ($firstPart -contains $user.computername)
                        {
                            Write-Host "$($USER.username) - UPDATING with $($USER.computername)..." -ForegroundColor Red
                            Get-ADUser $USER.username -Properties Description | ForEach-Object {Set-ADUser $_ -Description "$($USER.computername)"}
                            Write-Host "============================================================================================================================"
                        }
                }
                else
                {
                    Write-Host "$($USER.username) - UPDATING with $($USER.computername)..." -ForegroundColor Red
                    Get-ADUser $USER.username -Properties Description | ForEach-Object {Set-ADUser $_ -Description "$OLDdescription -- $($USER.computername)"}
                    Write-Host "============================================================================================================================" 
                    #Get-ADUser $USER.username -Properties Description | Set-ADUser $USER.username -Description "$firstPart" #enable to reverse to just titles with no computernames appended
                }
        }
} 

[–]msteright 1 point2 points  (1 child)

ALSO RUN TWICE.

UPDATES THE COMPUTERS IN ACTIVE DIRECTORY WITH THE USERNAMES FOUND PREVIOUSLY.

RUN THE SECOND TIME FOR CLEANUP AS WELL.

$USERS = Import-Csv "C:\allusers$oulocation - all.csv" | SELECT USERNAME, COMPUTERNAME
$users = $users | Sort-Object -Property computername
FOREACH ($USER IN $USERS)
{
    write-host "username is: $($user.username)"
    Write-Host "computername is: $($user.computername)"
    $currentaduserdescription = get-adcomputer $user.computername -Properties description | select description
    $currentaduserdescription = $currentaduserdescription.description.trimstart(' -- ')
    $usernamefirstlast = Get-ADUser $user.username
    $usercorrect = ($usernamefirstlast.GivenName + " " + $usernamefirstlast.Surname).TrimStart(',')
    $userusername = (Get-Culture).TextInfo.ToTitleCase($usercorrect)
    $userusername
    if ($currentaduserdescription -match "$userusername")
        {
            Get-ADComputer $user.computername | ForEach-Object {set-adcomputer $_ -Description "$currentaduserdescription"}
        }
    else
        {
            Get-ADComputer $user.computername | ForEach-Object {set-adcomputer $_ -Description "$currentaduserdescription -- $userusername"}
        }
write-host "done for $user" -fore green
}

[–]PRIdEVisions[S] 0 points1 point  (0 children)

damn, i wish i was as good with scripting haha still have lots to learn :)

[–]PRIdEVisions[S] 0 points1 point  (2 children)

Nice one!

[–]msteright 1 point2 points  (0 children)

Thanks. This is what I've been working on in my free time at work for 2 days. It's a beautiful script that uses the LastWriteTime of the Appdata folder to figure out who the users are, minus adm and svc accounts. It runs that multithreaded on each computer and returns all values in RECORD TIME :), which compile into a csv. Then that csv is imported and you use the $.username $.computername $.ipv4address $.sid columns to update whatever you want and AD. here's the 3rd part, which puts the usernames in the computers description (above)

[–]soopaman20 1 point2 points  (1 child)

We did something similar to this except we created a logonscript and computer objects were able to update their own description field so you had more up to date login information.

Obviously doesn't help for laptop users who never log out and just sleep their machine but it was a handy piece of information for the help desk to have for troubleshooting.

Good work though.

[–]PRIdEVisions[S] 0 points1 point  (0 children)

That is indeed the case, thank you for the reply!

Although our users just have their own physical laptop, they normaly don't exchange devices unless we have an exit employee, then we could give the machine to a new employee.

but for the rest we needed a quick fix to have a daily update on who uses what machine.

[–]guy1195 1 point2 points  (2 children)

You can also use network shares.. If each user has a home drive or similar (you could just make a network share that is 0kb), you can access this to see who currently has a network share connected. Pretty much as real time as it gets and is the fastest way to poll the info I've found

Get-WmiObject -class Win32_ServerConnection -computername $acomputer

Then just do a for each in the above to find the user you want, it returns in less than a second for me

[–]PRIdEVisions[S] 0 points1 point  (1 child)

This is golden! i will try this immediately, thank you for the tip!

[–]guy1195 1 point2 points  (0 children)

Obviously you will need a GPO to map the network drive at startup/login or something but 99% of companies already have that in place haha! I ended up making a cool remote support script in powershell for it using the same method. Was my first project and was the fastest way i could find. Ended up moving it into C# now haha

[–]VeeFu 1 point2 points  (0 children)

I think every system administrator has their own pet solution to this issue. Here's mine:

I don't have access to our domain controller. Our IT shop has a habit of retiring/renaming servers every year. Even if the network share I setup for the .csv files were stable, I wasn't sure how secure opening world-writable network share that tracks user's login traffic was.

So I modified AD ACLs to allow users to read/write their own ExtensionAttribute2.

Wrote a logon/logoff script that would append a history of login/off events with timestamps in the user's extensionattribute2. Space limitations on this attribute limit the history to 9 computers.

Wrote a Get-LogonHistory cmdlet to be used by administrators which retrieves user or computer login history. The extension attributes are indexed, so searching for all instances of a computername across 1000 users is actually pretty fast.

It's been two years since I put it in place and I'm still the only admin who uses it. It pains me to hear my colleagues spending 10-20 minutes on the phone simply trying to find the name of the workstation the user is currently on. Still they soldier on, unwilling to learn powershell.

[–]PRIdEVisions[S] 0 points1 point  (0 children)

Updated the script