PowerShell: obtener todos los usuarios conectados por computadora/unidad organizativa/dominio (Get-UserLogon)
Recientemente me preguntaron cómo mostrar todos los usuarios conectados. Entonces tuve la idea de convertirlo en una función. Y ahora compartiré esta función con la comunidad. ¿Quién inició sesión en qué computadora y cuándo? Ésa es la pregunta para este artículo. En realidad, la pregunta principal es: ¿Quién está conectado actualmente?
El requisito previo para este artículo es un entorno de Active Directory limpio y ordenado. ¿Por qué? Porque se necesitan unos 4 segundos para consultar al usuario que ha iniciado sesión en una computadora. Si todavía hay cuentas de ordenador en la base de datos que ya no se utilizan, llevará más tiempo innecesariamente. Especialmente si intentas consultar todo el dominio. Profundicemos.
La meta
El objetivo es una función que muestra todos los usuarios conectados por nombre de computadora o unidad organizativa. También es posible consultar todas las computadoras de todo el dominio. Tenga en cuenta que esto podría llevar algún tiempo. En mi entorno de prueba, tomó un promedio de aproximadamente 4 segundos por computadora.
En acción
Computadora
Obteniendo el usuario conectado de client01. Es Petra. Ella inició sesión a las 06:41 p.m.
Get-UserLogon -Computer client01
UNED
Digamos que tenemos estaciones de trabajo OU. Si desea recuperar todos los usuarios conectados de todas las computadoras en esta unidad organizativa, ejecute
Get-UserLogon -OU 'ou=Workstations,dc=sid-500,dc=com'
El segundo ejemplo muestra el usuario que ha iniciado sesión actualmente en todos los controladores de dominio.
Ok, tengo que admitir que mi pantalla es un poco aburrida. Estoy en un pequeño entorno de prueba de Active Directory. ?
Dominio completo
Lo que me lleva al último parámetro. Es un parámetro de cambio. No proporciones un valor.
Get-UserLogon -All
Vale eso es todo. Creo que esto es bastante útil para muchos de nosotros.
La función Get-UserLogon
Y aquí está la función en sí:
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
}
Nota importante sobre el idioma del sistema operativo
Tenga en cuenta que la función anterior utiliza el comando quser que genera texto sin formato. Hay diferencias entre p.e. Servidores alemanes y servidores ingleses. Esto significa que obtendrá el resultado que se muestra arriba solo en sistemas operativos en inglés.
Hazlo permanente
Si le gusta mi enfoque, abra PowerShell ISE. Copie la función en su sesión ISE. Cree una carpeta en C:\Program Files\Windows PowerShell\Modules y guarde el código como archivo psm1. Asegúrese de que el nombre de su archivo y el nombre de la carpeta coincidan.
De ahora en adelante, PowerShell cargará el módulo personalizado cada vez que se inicie PowerShell.
Agradecimientos
Gracias a Jaap Brasser (MVP) por su increíble función Get-LoggedOnUser. Su función fue de gran ayuda para mí y me inspiró a dar un paso más y llamar a todos los usuarios conectados por unidad organizativa o por todo el dominio.
Su función se puede encontrar aquí:
https://gallery.technet.microsoft.com/scriptcenter/Get-LoggedOnUser-Gathers-7cbe93ea



