List users logged on to your machines

Polityki haseł są najlepsze 😀 Czasami jednak prowadzą do wylogowania konta gdy ktoś zapomni wylogować się z sesji gdzieś w sieci. Może to być sesja TS, której używają raz na kwartał do raportowania, a może znasz to uczucie, gdy po przejściu przez RDP na serwer okazuje się, że jest on zablokowany przez 2 innych adminów, którzy zapomnieli się wylogować, gdy wyszli. (Off cause this never happens… we all use PowerShell…) Anyway, this had me searching for a user session somewhere on the network. Najgorszą rzeczą jest, gdy moje własne hasło wygasa. Nienawidzę, gdy moje konto kończy się zablokowaniem. Dlatego też uczyniłem to regułą, aby po prostu sprawdzić wszystkie serwery przed zmianą hasła. Istnieje wiele sposobów, aby to zrobić, ale oczywiście mam tendencję, aby przejść do trasy PowerShell.

Badania

Pierwotna metoda, której użyłem jest z galerii TechNet

W skrócie: Get-WmiObject -Class Win32_process

To w zasadzie znajduje wszystkich unikalnych użytkowników uruchamiających procesy na maszynie. Jest to fajne, ponieważ znajduje wszystko, nawet rzeczy działające jako usługi, ale nie jestem przekonany, że jest to najbardziej efektywny sposób.

Sprawdzając w google znalazłem wiele kreatywnych sposobów na sprawdzenie kto jest zalogowany na twoim komputerze.

peetersonline.nl/2008/11/oneliner-get-logged-on-users-with-powershell/ dał mi pomysł, aby sprawdzić Win32_LoggedOnUser co wydaje się oczywiste.

2015-08-28 (1)

To wygląda świetnie i wydaje się, że działa również z Get-CimInstance, chociaż dane wyjściowe są nieco inne.

2015-08-28

learn-powershell.net/…/Quick-hit-find-currently-logged-on-users/ przyjął trochę bardziej oldschoolowe podejście, które mi się podoba, ponieważ jest trochę szorstkie i zmusza mnie do zabawy z moim parsowaniem opartym na szablonach.

2015-08-28 (2)

Nie jestem pewien, która metoda jest szybsza, więc dlaczego nie spróbować zaimplementować wszystkich 3 w module i przetestować to.

Sketching

Zawsze dobrze jest zacząć od zrobienia szkicu tego, co próbujesz osiągnąć.

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

Teraz mam wszystkie informacje, których potrzebuję, aby skonfigurować repozytorium GitHub.

github.com/mrhvid/Get-ActiveUser

Code

Przede wszystkim interesujące mnie parametry to ComputerName i Method.

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

Mam już w głowie 3 możliwe Methods, więc ustawiam ValidateSet z tymi 3 możliwościami. Wtedy nie muszę się martwić o to wejście później.

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

W części Process mojej funkcji po prostu używam przełącznika dla 3 różnych metod, które pozwoliłem w Parameter.

Teraz jest to podstawowe wypełnienie pustych pól.

WMI

Moje stare rozwiązanie jest simpel i działa dobrze.

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

2015-08-28 (3)

Ale teraz, gdy znalazłem Win32_LoggedOnUser, wydaje się, że źle jest robić to w ten sposób. Lets look at the new idea instead.

2015-08-28 (4)

gwmi-Wmi32_LoggedOnUser_gm

To są wszystkie właściwe dane, ale wydaje się, że są one w formacie ciągów znaków, więc będę musiał zrobić trochę manipulacji. Można to zrobić na milion sposobów.

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

Wspomniany wcześniej one-liner Petera nie wydawał mi się zbyt przyjazny dla czytelnika, co jest ok jak na one-liner, ale chciałbym, aby był nieco bardziej czytelny, jeśli to możliwe.

$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)

To wydaje się w porządku 🙂 Zapiszę dane wyjściowe w zmiennej $ActiveUsers i zrobię to samo dla CIM i Query.

CIM

Spróbujmy z CIM.

2015-08-28 (6)

To wygląda o wiele bardziej uporządkowane.

2015-08-28 (7)

CIM kończy się jako łatwy do zrozumienia one-liner 😀

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

Query

Używając dobrego ol’ Query.exe znalazłem omówiony wcześniej parsowanie oparte na szablonach bardzo przydatne.

$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

Teraz muszę tylko sformatować i wyprowadzić użytkowników w ładny sposób. Chcę mieć czyste obiekty z ComputerName i UserName.

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

Testowanie

Teraz mam problem. Nie mogę tego przetestować, ponieważ nie mam kilku serwerów testowych do mojej dyspozycji. Wszystkie moje testy zostały przeprowadzone na moim własnym komputerze z Windows 10. Wygląda na to, że zapytanie jest o wiele szybsze działające lokalnie, ale WMI/CIM może dać bardziej kompletny widok na to, jakie usługi są uruchomione.

get-activeuser_wmi_highlight

Mam kilka standardowych kont usług działających, które mogą być miłe do usunięcia z danych wyjściowych. Ponadto, aby to było użyteczne, będziemy chcieli uruchomić to na wielu maszynach.

get-activeuser_query

Połączenie Get-ActiveUser z Start-Multithread z ostatniego tygodnia wydaje się działać zgodnie z przeznaczeniem.

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

Przekazanie powyższego do Out-GridView jest moim ulubionym sposobem na osiągnięcie czegoś naprawdę użytecznego.

get-activeuser_query_out-gridview

Teraz mamy wszystkie dane w ładny, przeszukiwalny sposób i naprawdę łatwo jest sprawdzić czy użytkownik jest zalogowany na jakiejś losowej maszynie. Jest to również łatwy sposób na sprawdzenie użytkowników rouge w twojej sieci.

Publikacja i opinie

Kod jest opublikowany na PowerShellGallery.

Proszę pomóż mi testując go dla mnie. Bardzo chciałbym wiedzieć, czy to działa w prawdziwym świecie 🙂

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

To powinno działać, gdy masz zainstalowany WMF 5 + i na Windows 10 po wyjęciu z pudełka.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.