a better way to find a logged on user remote using PowerShell

There are a mountain of different ways to get logged on users, but I have a favorite! Käyttämällä qwinsta ainoa ongelma on, että se palauttaa merkkijonon ja PowerShell tykkää objekteista : (but never fear! Voimme korjata sen.

qwinsta

esiasetukset

törmäsin virheeseen 5 access denied issue kun aloin käyttää qwinsta, siihen on olemassa rekisterikorjaus (kiitos StackOverflow:

"AllowRemoteRPC"=dword:00000001

koska tämä on PowerShell-blogi, tässä on PowerShell-syntaksi, jolla voit lisätä sen etätietokoneeseen, koska työskentelemme todennäköisesti etätietokoneilla.

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

syntaksi

qwinstan syntaksi on melko suoraviivainen:

qwinsta /server:ServerName

ja lähtö näyttää melko unmenacing:

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

ainoa ongelma on, että jos etsit RDS-palvelinta, ei ole helppoa tapaa suodattaa merkkijonoja Powershellissa. Joten et voinut tehdä jotain … :

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

mutta voimme korjata sen! Lets wrap qwinsta jotta voimme esineellistää että lähtö!

Wrapping qwinsta

we ‘ re going to create a PowerShell function here, reader beware.

vääntämällä merkkijonoa sen arvoille

kaiken parametrin lisäksi, johon pääsemme, ensimmäinen ydinasia, jonka teemme, on ohjata lähtö muuttujaan:

$result = qwinsta /server:$ComputerName

nyt $result näyttää aivan samalta kuin aikaisempi ulostulo, mutta se muotoillaan merkkijonorivistöksi (string). Voimme tietenkin tarkistaa, että Get-Member:

($result | Get-Member).TypeName

seuraavaksi haemme haluamamme tiedot. Olen päättänyt for loop, ohita ensimmäinen rivi, koska emme tarvitse otsikot:

ForEach($line in $result)

kunkin rivin, mikä on kunkin arvon rajattu kanssa? Välilyöntejä! Joten voimme käyttää sitä .Split () menetelmä merkkijonoja ja jakaa jokaisen välilyönnin. Ainoa varoitus on, että meidän täytyy myös testata arvoa jokaiselle jaetulle, koska voit jakaa useita välilyöntejä ja saada nolla-arvoja.

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

on huomattava, että lähtö qwinsta on tasalevyinen, eli leveys ei muutu riippumatta siitä, kuinka pitkiä arvot ovat. Voimme hyödyntää sitä ja käyttää tiettyjä indeksejä eduksemme.

ensimmäiseksi on selvitettävä, mitkä rivit todella sisältävät käyttäjän. Voimme laskea merkkejä ja todeta, että käyttäjätunnuksen arvo alkaa 19.merkki (ensimmäinen merkki on todella tilaa, Katso huolellisesti). Joten jos 19. merkki ei ole tyhjä, meillä on käyttäjä.

If(($line -ne " "))

seuraava asia, jonka huomasin testauksessa qwinsta, on, että SessionName-ominaisuudella on arvoa vain, jos istunto on ‘aktiivisessa’ tilassa. Joten meidän on myös tarkistettava, onko valtio “aktiivinen”, minkä voimme tehdä tarkistamalla kyseisen valtion indeksin “A’

If($line -eq "A")

jos se on “aktiivinen”, $tmp – muuttujalla on erilaisia arvoja.

Aktiivinen:

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

Ei Käytössä:

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

muunnetaan arvot käyttökelpoisiksi kohteiksi

kun kaikki arvot on selvitetty, voidaan luoda uusi PSObject, suosikkini! Jos sinulla on PowerShellv5, voit käyttää {} type acceleratoria (x), Mutta minä käytän New-Object cmdlet tässä lopulliseen yhteensopivuuteen.

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

tässä tapauksessa, koska tiedämme istunnon olevan aktiivinen, ensimmäinen merkkijono $tmp on istunnon nimi, ja sitten, järjestyksessä, sinulla on loput ominaisuudet. On mahdollista, että “Tyyppi” tai “Sessioname” voi palata tyhjänä.

jos valtio ei ole “aktiivinen”, vaihtaisimme sen:

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

lopputuote

koska tämä ei ole viesti funktioiden luomisesta, Aion ohittaa muun syntaksin ja näyttää lopullisen funktion, jonka kirjoitin. Tämä sisältää joitakin parhaita käytäntöjä juttuja, kuten tarkistaa yhteyden ja admin oikeudet ennen päästä jännittävä tavaraa.

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

tämän löydät Apuohjelmistani GitHub reposta. Tämä on ensimmäinen julkaistu käsikirjoitukseni! Hurraa! Joten mennään yli, miten sitä käytetään:

yksinkertainen käyttö

hakeaksemme käyttäjät, jotka ovat kirjautuneet etätietokoneeseen tai paikalliseen tietokoneeseen, käyttäisimme yksinkertaisesti:

Get-ActiveSessions ComputerName

ja tämän pitäisi palauttaa jotain vastaavaa:

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

ja jos siirrät sen muuttujaan ja katsot tyypin nimeä, meillä pitäisi olla PSCustomObject, eli voimme käyttää kaikkia muita hyödyllisiä cmdletejä suodatukseen ja muuhun!

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

Advanced usage

meillä on tässä kaksi asiaa, voimme hyväksyä putkilinjan syötön ja se ouputs objekti. Joten voimme tehdä juttuja ennen ja jälkeen Get-ActiveSessions.

mitä jos haluat löytää kaikki ympäristöstäsi olevat palvelimet, joihin on kirjautunut tietty käyttäjä?

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

tai mitä jos vetäisit listan tietokoneista tekstitiedostosta ja tulostaisit listan ainutlaatuisista käyttäjistä, jotka ovat kirjautuneet niihin kaikkiin?

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

jos keksit Get-ActiveSessions hyödyllisiä käyttötarkoituksia, kommentoi!

loppupäätelmä

toivottavasti osaat arvostaa sitä, miksi kirjoittaisin funktion, jolla tekisin nämä jutut puolestani. En osannut laskea, kuinka monta kertaa olen käyttänyt tätä helpottaakseni työtäni.

Anyways, minulla on pari merkittävää virkaa tulossa, erityisesti kumppani Get-ActiveSessions: Close-ActiveSessions.

spoileri:

Get-ActiveSessions Computer | Close-ActiveSessions

ja myös:’ luominen ajoitettu tehtäviä PowerShell skriptejä’, joka on matka, koska en ole tehnyt mitään kuvia vielä!

Leave a Reply