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-ActiveSessions
elő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