Liste over brugere, der er logget på dine maskiner

Password-politikker er de bedste 😀 Nogle gange fører de dog til logout af konti, når nogen glemmer at logge ud af en session et sted på netværket. Det kan være TS-sessionen, som de bruger en gang i kvartalet til rapportering, eller måske kender du følelsen, når du RDP til en server kun for at finde ud af, at den er låst af 2 andre admins, der har glemt at logge af, da de gik. (Off cause this never happens… we all use PowerShell…) Anyway, this had me searching for a user session somewhere on the network. Det værste er, når min egen adgangskode udløber. Jeg hader, når min konto ender med at blive låst. Derfor har jeg gjort det til en regel at bare tjekke alle servere, før jeg ændrer password. Der er flere måder at gøre dette på, men jeg har selvfølgelig en tendens til at gå PowerShell-ruten.

Research

Den oprindeligt metode jeg brugte er fra TechNet gallery

Kort sagt: Get-WmiObject -Class Win32_process

Dette finder dybest set alle unikke brugere, der kører processer på maskinen. Dette er cool, fordi det finder alt, selv ting, der kører som en tjeneste, men jeg er ikke overbevist om, at det er den mest effektive måde.

Tjekke op med google finder jeg en masse kreative måder at kontrollere, hvem der er logget på din boks.

peetersonline.nl/2008/11/oneliner-get-logged-on-users-with-powershell/ gav mig ideen til at kontrollere Win32_LoggedOnUser, som synes indlysende.

2015-08-28 (1)

Det ser godt ud og synes også at virke med Get-CimInstance, selv om output er lidt anderledes.

2015-08-28

learn-powershell.net/…/Quick-hit-find-currently-logged-on-users/ tog en lidt mere gammeldags tilgang, som jeg ligesom kan lide, fordi det er lidt groft og tvinger mig til at lege med min skabelonbaserede parsing.

2015-08-28 (2)

Jeg er ikke helt sikker på hvilken metode der er hurtigere, så hvorfor ikke prøve at implementere alle 3 i et modul og teste det af.

Skitsering

Det er altid en god idé at starte med at lave en skitse af hvad du prøver at opnå.

Pseudo code:Get-ActiveUser -ComputerName -Method Wanted output:Username ComputerName-------- ------------TestUser1 Svr3TestUser3 Svr3DonaldDuck Client2

Nu har jeg alle de oplysninger, jeg skal bruge til at oprette GitHub-repositoriet.

github.com/mrhvid/Get-ActiveUser

Kode

Først af alt er de parametre, jeg er interesseret i, ComputerName og Method.

 Param ( # Computer name, IP, Hostname ] $ComputerName, # Choose method, WMI, CIM or Query $Method )

Jeg har allerede 3 mulige Methods i tankerne, så jeg indstiller ValidateSet med de 3 muligheder. Så behøver jeg ikke at bekymre mig om det input senere.

 Process { switch ($Method) { 'WMI' { } 'CIM' { } 'Query' { } } }

I Process-delen af min funktion bruger jeg simpelthen en switch for de 3 forskellige metoder, som jeg tillod i Parameter.

Nu er det grundlæggende udfyldning af felter.

WMI

Min gamle løsning er simpel og fungerer fint.

$WMI = Get-WmiObject -Class Win32_Process -ComputerName $ComputerName -ErrorAction Stop$ProcessUsers = $WMI.getowner().user | Select-Object -Unique

2015-08-28 (3)

Men nu da jeg fandt Win32_LoggedOnUser virker det forkert at gøre det på denne måde. Lad os se på den nye idé i stedet.

2015-08-28 (4)

gwmi-Wmi32_LoggedOnUser_gm

Dette er alle de rigtige data, men det ser ud til at være i et string-format, så jeg bliver nødt til at lave lidt manipulation. Det kan gøres på en million måder.

function Get-MyLoggedOnUsers { param($Computer) Get-WmiObject Win32_LoggedOnUser -ComputerName $Computer | Select Antecedent -Unique | %{"{0}{1}" -f $_.Antecedent.ToString().Split('"'), $_.Antecedent.ToString().Split('"')} }

Peters førnævnte one-liner virkede ikke særlig læsevenlig på mig, hvilket er ok for en one-liner, men jeg vil gerne have den lidt mere læsevenlig, hvis det er muligt.

$WMI = (Get-WmiObject Win32_LoggedOnUser).Antecedent$ActiveUsers = @()foreach($User in $WMI) { $StartOfUsername = $User.LastIndexOf('=') + 2 $EndOfUsername = $User.Length - $User.LastIndexOf('=') -3 $ActiveUsers += $User.Substring($StartOfUsername,$EndOfUsername)}

2015-08-28 (5)

Det ser rigtigt ud 🙂 Jeg gemmer outputtet i variablen $ActiveUsers og gør det samme for CIM og Query.

CIM

Lader os prøve med CIM.

2015-08-28 (6)

Det ser langt mere struktureret ud.

2015-08-28 (7)

CIM ender med at blive en letforståelig one-liner 😀

$ActiveUsers = (Get-CimInstance Win32_LoggedOnUser -ComputerName $ComputerName).antecedent.name | Select-Object -Unique

Query

Ved hjælp af den gode gamle Query.exe fandt jeg den tidligere omtalte skabelonbaserede parsing meget nyttig.

$Template = @' USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME>{USER*:jonas} console 1 Active 1+00:27 24-08-2015 22:22 {USER*:test} 2 Disc 1+00:27 25-08-2015 08:26'@$Query = query.exe user$ActiveUsers = $Query | ConvertFrom-String -TemplateContent $Template | Select-Object -ExpandProperty User

Output

Nu skal jeg bare formatere og outputte brugerne på en pæn måde. Jeg vil have rene objekter med ComputerName og UserName.

# Create nice output format$UsersComputersToOutput = @()foreach($User in $ActiveUsers) { $UsersComputersToOutput += New-Object psobject -Property @{ ComputerName=$ComputerName; UserName=$User } }}# output data$UsersComputersToOutput

Testing

Nu har jeg et problem. Jeg kan ikke teste dette, da jeg ikke har en masse testserveres til min rådighed. Alle mine tests er blevet udført mod min egen Windows 10-boks. Det er ser ud til at forespørgsel er meget hurtigere at køre lokalt, men WMI/CIM kan give et mere komplet overblik over hvilke tjenester der kører.

get-activeuser_wmi_highlight

Jeg har en masse standard tjenestekonti kørende, som det kunne være rart at fjerne fra output. Også for at dette skal være nyttigt vil vi ønske at køre det mod en masse maskiner.

get-activeuser_query

Kombination af Get-ActiveUser med Start-Multithread fra sidste uges indlæg ser ud til at virke efter hensigten.

Start-Multithread -Script { param($C) Get-ActiveUser -ComputerName $C -Method Query } -ComputerName ::1,Localhost | Out-GridView

Piping ovenstående til Out-GridView er proberbly min personlige favorit måde at opnå noget virkelig nyttigt.

get-activeuser_query_out-gridview

Nu har vi alle data i en dejlig søgbar måde, og det er virkelig nemt at kontrollere, om din bruger er logget ind på en tilfældig maskine. Det også en nem måde at tjekke for rouge brugere på dit netværk.

Publicering og feedback

Koden er publiceret på PowerShellGallery.

Hjælp mig gerne ved at teste den for mig. Jeg vil meget gerne vide, om det virker i den virkelige verden 🙂

# To install Get-ActiveUserInstall-Module Get-ActiveUser#To install Start-MultithreadInstall-Module Start-Multithread

Dette skulle virke, når du har WMF 5 + installeret og på Windows 10 out of the box.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.