a jobb módja annak, hogy megtalálja a bejelentkezett felhasználó távolról PowerShell

van egy hegy különböző módon, hogy bejelentkezett felhasználók, de van egy kedvenc! A qwinsta használatával az egyetlen probléma az, hogy visszaad egy karakterláncot, és a PowerShell kedveli az objektumokat : (de soha ne félj! Meg tudjuk oldani.

qwinsta

Prereqs

belefutottam egy hiba 5 hozzáférés megtagadva kérdés, amikor elkezdtem használni qwinsta, van egy registry fix, hogy (köszönöm StackOverflow:

"AllowRemoteRPC"=dword:00000001

mivel ez egy PowerShell blog, itt található a PowerShell szintaxisa, amellyel hozzáadhatja egy távoli számítógéphez, mivel valószínűleg távoli számítógépeken fogunk dolgozni.

$ComputerName = 'Computer' #replace with the computer name$LMtype = ::LocalMachine$LMkey = "SYSTEM\CurrentControlSet\Control\Terminal Server"$LMRegKey = ::OpenRemoteBaseKey($LMtype,$ComputerName)$regKey = $LMRegKey.OpenSubKey($LMkey,$true)If($regKey.GetValue("AllowRemoteRPC") -ne 1){ $regKey.SetValue("AllowRemoteRPC",1) Start-Sleep -Seconds 1}$regKey.Dispose()$LMRegKey.Dispose()

szintaxis

a qwinsta szintaxisa meglehetősen egyszerű:

qwinsta /server:ServerName

a kimenet pedig meglehetősen unmenacingnek tűnik:

 SESSIONNAME USERNAME ID STATE TYPE DEVICE services 0 Disc console Anthony 1 Active rdp-tcp 65536 Listen

az egyetlen probléma az, hogy ha RDS szervert nézett, akkor nincs egyszerű módszer a karakterláncok szűrésére a PowerShell-ben. Tehát nem tehettél valami ilyesmit:

qwinsta /server:RDSServer | Where-Object USERNAME -like "Anth*"

de meg tudjuk oldani! Lets wrap qwinsta úgy, hogy tudjuk tárgyiasítani, hogy a kimenet!

csomagolás qwinsta

fogunk létrehozni egy PowerShell funkció itt, olvasó vigyázz.

a karakterlánc kicsavarása az értékeihez

az összes paraméter mellett, amelyhez eljutunk, az első alapvető dolog, amit megteszünk, az, hogy a kimenetet egy változóra irányítjuk:

$result = qwinsta /server:$ComputerName

most $result fog kinézni, mint a kimenet előtt, de ez lesz formázva, mint egy string tömb (string). Tudjuk, természetesen, ellenőrizze, hogy a Get-Member:

($result | Get-Member).TypeName

tehát a következő dolog az, hogy csak a kívánt információt szerezzük be. Úgy döntöttem, hogy a For hurok, kihagyva az első sort, mivel nincs szükségünk a fejlécekre:

ForEach($line in $result)

minden sorhoz, mi az egyes értékek határolva? Szóközök! Így tudjuk használni a .Split() metódus a karakterláncokon és minden szóközzel osztva. Az egyetlen figyelmeztetés az, hogy minden felosztásnál meg kell vizsgálnunk az értéket, mivel több szóközt is feloszthat, és null értékeket kaphat.

$tmp = $line.split(" ") | ?{$_.length -gt 0}

egy dolgot meg kell jegyezni, hogy a qwinsta kimenete rögzített szélességű, ami azt jelenti, hogy a szélesség nem változik, függetlenül attól, hogy az értékek milyen hosszúak. Ezt kihasználhatjuk, és bizonyos indexeket előnyünkre fordíthatunk.

először meg kell határozni, hogy mely sorok tartalmazzák a felhasználót. Megszámolhatjuk a karaktereket, és megállapíthatjuk, hogy a felhasználónév értéke a 19.karakternél kezdődik (az első karakter valójában a szóköz, nézd meg alaposan). Tehát, ha a 19. karakter nem üres, akkor van egy felhasználónk.

If(($line -ne " "))

a következő dolog, amit észrevettem a qwinsta tesztelésénél, az, hogy a SessionName tulajdonságnak csak akkor van értéke, ha a munkamenet ‘aktív’ állapotban van. Tehát azt is ellenőriznünk kell, hogy az állapot ‘aktív’ – e, amit megtehetünk, ha ellenőrizzük az adott állapot indexét egy ‘A-ra’

If($line -eq "A")

ha ‘aktív’, akkor a $tmp változónak különböző értékei lesznek.

Aktív:

#raw rdp-tcp#0 anthony 2 Active #$tmp variable (split)rdp-tcp#0anthony2Active

Nem Aktív:

#raw anthony 2 Disc #$tmp variable (split)anthony2Disc

az értékek konvertálása használható objektumokká

miután minden értéket kitaláltunk, létrehozhatunk egy új PSObject-et, a kedvencemet! Ha van PowerShellv5, akkor használhatja a {} típusú gyorsítót (x), de itt a New-Object parancsmagot fogom használni a végső kompatibilitás érdekében.

New-Object PSObject -Property @{ "ComputerName" = $ComputerName "SessionName" = $tmp "UserName" = $tmp "ID" = $tmp "State" = $tmp "Type" = $tmp}

ebben az esetben, mivel tudjuk, hogy a munkamenet aktív, a $tmp első karakterlánca a munkamenet neve, majd sorrendben megvan a többi tulajdonság. Lehetséges ,hogy a’ típus ‘vagy a’ SessionName ‘ üresen tér vissza.

ha az állapot nem ‘aktív’, akkor ezt a:

New-Object PSObject -Property @{ "ComputerName" = $ComputerName "SessionName" = $null "UserName" = $tmp "ID" = $tmp "State" = $tmp "Type" = $null}

a végtermék

mivel ez nem a funkciók létrehozásáról szóló bejegyzés, átugrom a többi szintaxist, és megmutatom az általam írt végső függvényt. Ez magában foglal néhány bevált gyakorlatot, például a kapcsolat és az adminisztrátori jogok ellenőrzését, mielőtt az izgalmas dolgokba kerülne.

Function Get-ActiveSessions{ Param( $Name , $Quiet ) Begin{ $return = @() } Process{ If(!(Test-Connection $Name -Quiet -Count 1)){ Write-Error -Message "Unable to contact $Name. Please verify its network connectivity and try again." -Category ObjectNotFound -TargetObject $Name Return } If(((::GetCurrent()).groups -match "S-1-5-32-544")){ #check if user is admin, otherwise no registry work can be done #the following registry key is necessary to avoid the error 5 access is denied error $LMtype = ::LocalMachine $LMkey = "SYSTEM\CurrentControlSet\Control\Terminal Server" $LMRegKey = ::OpenRemoteBaseKey($LMtype,$Name) $regKey = $LMRegKey.OpenSubKey($LMkey,$true) If($regKey.GetValue("AllowRemoteRPC") -ne 1){ $regKey.SetValue("AllowRemoteRPC",1) Start-Sleep -Seconds 1 } $regKey.Dispose() $LMRegKey.Dispose() } $result = qwinsta /server:$Name If($result){ ForEach($line in $result){ #avoiding the line 0, don't want the headers $tmp = $line.split(" ") | ?{$_.length -gt 0} If(($line -ne " ")){ #username starts at char 19 If($line -eq "A"){ #means the session is active ("A" for active) $return += New-Object PSObject -Property @{ "ComputerName" = $Name "SessionName" = $tmp "UserName" = $tmp "ID" = $tmp "State" = $tmp "Type" = $tmp } }Else{ $return += New-Object PSObject -Property @{ "ComputerName" = $Name "SessionName" = $null "UserName" = $tmp "ID" = $tmp "State" = $tmp "Type" = $null } } } } }Else{ Write-Error "Unknown error, cannot retrieve logged on users" } } End{ If($return){ If($Quiet){ Return $true } Else{ Return $return } }Else{ If(!($Quiet)){ Write-Host "No active sessions." } Return $false } }}

Get-ActiveSessions

megtalálható ez az én Utilities GitHub repo. Ez az első megjelent forgatókönyvem! Hurrá! Tehát menjünk át, hogyan kell használni:

Egyszerű használat

a távoli vagy helyi számítógépre bejelentkezett felhasználók letöltéséhez egyszerűen használnánk:

Get-ActiveSessions ComputerName

ennek valami hasonlót kell visszaadnia:

ID : 2SessionName :Type :UserName : anthonyComputerName : dc01State : Disc

és ha átadjuk egy változónak, és megnézzük a típusnevet, akkor PSCustomObject – nak kell lennie, ami azt jelenti, hogy az összes többi hasznos parancsmagot felhasználhatjuk szűrésre és miegymás!

$sessions = Get-ActiveSessions ComputerName($sessions | Get-Member).TypeNameSystem.Management.Automation.PSCustomObject

Advanced usage

van két dolog megy nekünk itt, tudjuk fogadni csővezeték bemenet és ez ouputs egy objektumot. Tehát csinálhatunk dolgokat a Get-ActiveSessionselőtt és után.

mi van, ha meg akarja találni az összes olyan kiszolgálót a környezetében, amelybe egy adott felhasználó be van jelentkezve?

Get-ADComputer -Filter {OperatingSystem -like '*Server*'} | Get-ActiveSessions | Where-Object UserName -eq 'Anthony'

vagy mi lenne, ha egy szöveges fájlból kihúzná a számítógépek listáját, és kiadná az összes bejelentkezett egyedi felhasználó listáját?

get-content C:\temp\computers.txt | Get-ActiveSessions | Select-Object -Unique UserName -ExpandProperty UserName | Out-File C:\temp\users.txt

ha felér bármilyen hasznos felhasználása Get-ActiveSessions, megjegyzést!

következtetés

remélhetőleg van egy elismerését, hogy miért írnék egy függvényt, hogy ezt a dolgot nekem. Őszintén nem tudtam megszámolni, hányszor használtam ezt a munkám megkönnyítésére.

egyébként, van egy pár figyelemre méltó hozzászólás jön, különösen a partner Get-ActiveSessions: Close-ActiveSessions.

Spoiler:

Get-ActiveSessions Computer | Close-ActiveSessions

és még: ‘Ütemezett feladatok létrehozása a PowerShell szkriptekhez’, ami utazás lesz, mivel még nem készítettem képeket!

Leave a Reply