PowerShell

PowerShell: Get all logged on Users per Computer/OU/Domain (Get-UserLogon)

Recently I was asked how to show all logged on users. So I had the idea to make a function out of it. And now I’ll share this function to the community. Who logged on to which computer and when? That is the question for this article. Actually, the main question is: Who is currently logged in?

Prerequisite for this article is a tidy and clean Active Directory environment. Why? Because it takes about 4 seconds to query a computer’s logged on user. If there are still computer accounts in the database which are no longer used, it will take needless longer. Especially if you try to query the entire domain. Let’s dive in.

The Goal

The target is a function that shows all logged on users by computer name or OU. It’s also possible to query all computers and users. Note that this could take some time. In my test environment it took about 4 seconds per computer on average.

In Action

Computer

Getting the logged on user of client01. It’s Petra. She logged in at 06:41 PM.


Get-UserLogon -Computer client01

1.PNG

OU

Let’s say we have an OU called Workstations. If you want to retrieve all logged on users of all computers from this OU then run


Get-UserLogon -OU 'ou=Workstations,dc=sid-500,dc=com'

Unbenannt.PNG

The second example shows the current logged on user on all Domain Controllers.

Ok I have to admit that my screen is a little boring. I’m in in a small Active Directory testing environment. 😉

Entire Domain

Which brings me to the last parameter. It’s a switch parameter. Don’t specify a value.


Get-UserLogon -All

Unbenannt.PNG

Ok, that’s it. I think this is quite helpful for many of us.

The Function Get-UserLogon

And here is the function itself:


function Get-UserLogon {

[CmdletBinding()]

param

(

[Parameter ()]
[String]$Computer,

[Parameter ()]
[String]$OU,

[Parameter ()]
[Switch]$All

)

$ErrorActionPreference="SilentlyContinue"

$result=@()

If ($Computer) {

Invoke-Command -ComputerName $Computer -ScriptBlock {quser} | Select-Object -Skip 1 | Foreach-Object {

$b=$_.trim() -replace '\s+',' ' -replace '>','' -split '\s'

If ($b[2] -like 'Disc*') {

$array= ([ordered]@{
'User' = $b[0]
'Computer' = $Computer
'Date' = $b[4]
'Time' = $b[5..6] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array

}

else {

$array= ([ordered]@{
'User' = $b[0]
'Computer' = $Computer
'Date' = $b[5]
'Time' = $b[6..7] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array

}
}
}

If ($OU) {

$comp=Get-ADComputer -Filter * -SearchBase "$OU" -Properties operatingsystem

$count=$comp.count

If ($count -gt 20) {

Write-Warning "Search $count computers. This may take some time ... About 4 seconds for each computer"

}

foreach ($u in $comp) {

Invoke-Command -ComputerName $u.Name -ScriptBlock {quser} | Select-Object -Skip 1 | ForEach-Object {

$a=$_.trim() -replace '\s+',' ' -replace '>','' -split '\s'

If ($a[2] -like '*Disc*') {

$array= ([ordered]@{
'User' = $a[0]
'Computer' = $u.Name
'Date' = $a[4]
'Time' = $a[5..6] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array
}

else {

$array= ([ordered]@{
'User' = $a[0]
'Computer' = $u.Name
'Date' = $a[5]
'Time' = $a[6..7] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array
}

}

}

}

If ($All) {

$comp=Get-ADComputer -Filter * -Properties operatingsystem

$count=$comp.count

If ($count -gt 20) {

Write-Warning "Search $count computers. This may take some time ... About 4 seconds for each computer ..."

}

foreach ($u in $comp) {

Invoke-Command -ComputerName $u.Name -ScriptBlock {quser} | Select-Object -Skip 1 | ForEach-Object {

$a=$_.trim() -replace '\s+',' ' -replace '>','' -split '\s'

If ($a[2] -like '*Disc*') {

$array= ([ordered]@{
'User' = $a[0]
'Computer' = $u.Name
'Date' = $a[4]
'Time' = $a[5..6] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array

}

else {

$array= ([ordered]@{
'User' = $a[0]
'Computer' = $u.Name
'Date' = $a[5]
'Time' = $a[6..7] -join ' '
})

$result+=New-Object -TypeName PSCustomObject -Property $array

}

}

}
}
Write-Output $result
}

Important Note regarding the Operating System Language

Be aware that the function above uses the quser command that outputs plain text. There are differences between e.g. German servers and English servers. This means, that you’ll get the output shown above only on Englisch operating systems.

Make it permanent

If you like my approach open PowerShell ISE. Copy the function into your ISE session. Create a folder in C:\Program Files\Windows PowerShell\Modules and save the code as psm1 file. Make sure that your file name and folder name match.

Unbenannt.PNG

From now on, PowerShell will load the custom module each time PowerShell is started.

Acknowledements

Thanks to Jaap Brasser (MVP) for his awesome function Get-LoggedOnUser. His function was a great help for me and it inspired me to get a step further and call all logged on users by OU or the entire domain.

His function can be found here:

https://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnUser-Gathers-7cbe93ea

21 replies »

  1. Hi Patrick, Got the script to work, except when using “All” – get the following:

    PS C:\windows\system32> get-userlogon -All
    Get-UserLogon : Missing an argument for parameter ‘All’. Specify a parameter of type ‘System.String’ and try again.
    At line:1 char:15
    + get-userlogon -All
    + ~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-UserLogon], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,Get-UserLogon

    Like

  2. Hello Patrick, thank you for this script – just what I am looking for. However when I run it, the prompt immediately returns with no results on the screen. I’ve copied your script with no alterations. Is there any external modules this script relies on that I may be missing? (Windows 7 workstation)

    Like

  3. Hi,
    I have tried this method many times, even tried to access the WMI for the user login details. You can get this data for online machines, but do you have any method to get this data directly from AD for all offline machines.

    Like

  4. Hi there, My script is not working and I am getting Error ( The term ‘Get-UserLogon’ is not recognized as the name of a cmdlet )…
    I basically want to get all user names and their respective computers names they use on Domain. Please help in finding such Powershell script.

    Like

  5. Hello, maybe you could look for the eventlog id then it would be no problem if one os is english and one os is german. Regards

    Like

  6. Hello,
    First, thanks a lot for this wonderful script.
    I just have one remark. If we run this script targeting a server on which WINRM is not installed, result will be null.
    Do you think it could work using “QWINSTA /server:” instead of “quser” ?
    In this way, using Invoke-Command won’t be necassary and solve the problem of WINRM.

    Best Regards.

    Jack!

    Like

    • Hi Jack!

      Thanks for your comment and compliment.
      You’ll also get a result of null if the computer is not switched on.

      Feel free to customize the script to your needs. I had the best results with quser.

      All the best,
      P

      Like

    • Hi!

      Thank you for comment.

      My command is a live query. What’s better depends on everyone’s needs.

      As mentioned in the article it will take about 4 seconds per computer. I am game with that in large environments searching the event logs will be the better solution, but remember that using quser on a client gives you different information than event logs.

      All the best,
      P

      Like

  7. Hello.

    Is it possible To get a list of installed application for each users or computer in domain?

    I can just extract list of all application from sccm but I want per user or machine

    Best Regards/ Cordialement

    Mounir

    +1 514 293 6955

    Like

    • Hi,

      Yes, run Get-CimInstance win32_product to get a list of all installed software on remote computers. But I guess SCCM should give you a list that meets your requirements.

      All the best,
      P

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s