source

원격 세션에서 Powershell 로그오프

ittop 2023. 10. 9. 23:31
반응형

원격 세션에서 Powershell 로그오프

사용자를 원격으로 로그오프하기 위해 파워셸 명령을 공식화하려고 합니다.우리는 때때로 세션을 잠그는 매우 불안정한 프로그램을 가진 터미널 서버를 가지고 있습니다.사용자를 원격으로 로그오프해야 하는데 스크립트를 실행한 사람을 로그오프하는 파워셸 문을 작성하려고 합니다.구글에서 검색해보니 다음 명령이 있었습니다.

Invoke-Command -ComputerName MyServer -Command {shutdown -l}

그러나 명령어는 "잘못된 기능"을 반환합니다.Get-Process와 같은 다른 명령을 괄호 안에서 성공적으로 실행할 수 있습니다.

이 아이디어는 사용자가 서버에서 스스로 로그오프하기 위해 실행할 수 있는 스크립트에 입력하는 것입니다(잠겼을 때 시작 메뉴나 ALT+CTRL+END에 액세스하여 GUI를 통해 실행할 수 없기 때문입니다).

흐름은 다음과 같습니다. Bob은 RDP를 통해 MyServer에 로그인하지만 세션이 중단됩니다.로컬 데스크톱에서 MyScript(위와 유사한 명령어 포함)를 실행하면 MyServer에서 세션이 로그오프됩니다.

아마도 놀랍게도 당신은 사용자들을 로그오프 할 수 있습니다.logoff지휘.

C:\> logoff /?
Terminates a session.

LOGOFF [sessionname | sessionid] [/SERVER:servername] [/V] [/VM]

  sessionname         The name of the session.
  sessionid           The ID of the session.
  /SERVER:servername  Specifies the Remote Desktop server containing the user
                      session to log off (default is current).
  /V                  Displays information about the actions performed.
  /VM                 Logs off a session on server or within virtual machine.
                      The unique ID of the session needs to be specified.

세션 ID는 다음과 같이 결정할 수 있습니다.qwinsta(query session) 또는quser(query user) 명령(여기 참조):

$server   = 'MyServer'
$username = $env:USERNAME

$session = ((quser /server:$server | ? { $_ -match $username }) -split ' +')[2]

logoff $session /server:$server

원격 또는 로컬에서 사용자를 로그아웃할 수 있는 훌륭한 스크립트 솔루션이 있습니다.저는 qwinsta를 사용하여 세션 정보를 얻고 주어진 출력으로 배열을 만들고 있습니다.이렇게 하면 대개 액세스 거부 오류를 발생시키는 시스템이나 RDP 수신기 자체가 아니라 각 항목을 반복하여 실제 사용자만 로그아웃할 수 있습니다.

$serverName = "Name of server here OR localhost"
$sessions = qwinsta /server $serverName| ?{ $_ -notmatch '^ SESSIONNAME' } | %{
$item = "" | Select "Active", "SessionName", "Username", "Id", "State", "Type", "Device"
$item.Active = $_.Substring(0,1) -match '>'
$item.SessionName = $_.Substring(1,18).Trim()
$item.Username = $_.Substring(19,20).Trim()
$item.Id = $_.Substring(39,9).Trim()
$item.State = $_.Substring(48,8).Trim()
$item.Type = $_.Substring(56,12).Trim()
$item.Device = $_.Substring(68).Trim()
$item
} 

foreach ($session in $sessions){
    if ($session.Username -ne "" -or $session.Username.Length -gt 1){
        logoff /server $serverName $session.Id
    }
}

이 스크립트의 첫 번째 행에 $serverName에 로컬로 실행되는 경우 적절한 값 또는 localhost를 지정합니다.자동화 프로세스가 일부 폴더를 이동하기 전에 이 스크립트를 사용하여 사용자를 불러옵니다."사용 중인 파일" 오류를 방지합니다.참고로, 이 스크립트는 관리자로 실행되어야 합니다. 그렇지 않으면 누군가를 로그아웃하려고 하면 접근이 거부될 수 있습니다.도움이 되길 바랍니다!

만약 누군가가 그렇게 기울어 있다면, 평범한 DOS 명령어를 추가하는 것.예, Win 8 및 Server 2008 + Server 2012에도 적용됩니다.

Query session /server:Server100

반환 예정:

SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE
rdp-tcp#0         Bob                       3  Active  rdpwd
rdp-tcp#5         Jim                       9  Active  rdpwd
rdp-tcp                                 65536  Listen

세션을 로그오프하려면 다음을 사용합니다.

Reset session 3 /server:Server100

이 학교는 오래된 학교이고 PowerShell보다 이전이지만, 오래된 RDP 세션을 원격으로 로그오프하기 위해 수년간 qwinsta/rwinsta 콤보를 사용했습니다.Windows XP 이상(이전 버전일 가능성도 있음)에 내장되어 있습니다.

세션 ID 결정:

qwinsta /SERVER:<NAME>

해당 세션을 제거합니다.

rwinsta <SESSION_ID> /SERVER:<NAME>

Invoke-RDUserLogoff를 사용할 수 있습니다.

특정 조직 단위의 Active Directory 사용자 로그오프 예:

$users = Get-ADUser -filter * -SearchBase "ou=YOUR_OU_NAME,dc=contoso,dc=com"

Get-RDUserSession | where { $users.sAMAccountName -contains $_.UserName } | % { $_ | Invoke-RDUserLogoff -Force }

파이프 끝에서 각(%)에 대해서만 사용하려고 하면 한 사용자만 로그오프됩니다.그러나 포어티와 파이프의 조합을 사용하면 다음과 같습니다.

| % {$_ | 명령 }

예상대로 작동할 것입니다.

Ps. Adm으로 실행합니다.

Terminal Services PowerShell 모듈을 사용해 보십시오.

Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force

저는 케이시의 대답을 다음과 같이 함으로써 로그오프 연결이 끊긴 세션으로만 수정했습니다.

   foreach($Server in $Servers) {
    try {
        query user /server:$Server 2>&1 | select -skip 1 | ? {($_ -split "\s+")[-5] -eq 'Disc'} | % {logoff ($_ -split "\s+")[-6] /server:$Server /V}
    }
    catch {}
    }

컴퓨터에서 모든 사용자 로그오프:

try {
   query user /server:$SERVER 2>&1 | select -skip 1 | foreach {
     logoff ($_ -split "\s+")[-6] /server:$SERVER
   }
}
catch {}

세부사항:

  • try/catch되며에 때 됩니다.query오류를 반환합니다.하지만, 당신은 그것을 떨어뜨릴 수 있습니다.2>&1을 제거합니다.try/catch면 을 보는요.
  • select -skip 1합니다를(를) 합니다.
  • foreach
  • ($_ -split "\s+")합니다인 .
  • [-6]는 세션 를 가져오고 에서 ID가입니다 6이기 때문에 . 왜냐하면 당신은 이것을 해야 합니다.query라 8다 9는에 이 끊겼는지에 9개의 를 갖습니다.

아래 스크립트는 사용자가 원격으로 logoff 명령을 실행할 수 있는 액세스 권한이 있는 한 활성 세션과 연결이 끊긴 세션 모두에서 잘 작동합니다.4번째 줄에 있는 "당신의 서버 이름"에서 서버 이름만 변경하면 됩니다.

param (
    $queryResults = $null,
    [string]$UserName = $env:USERNAME,
    [string]$ServerName = "YourServerName"
)


if (Test-Connection $ServerName -Count 1 -Quiet) {  
    Write-Host "`n`n`n$ServerName is online!" -BackgroundColor Green -ForegroundColor Black


    Write-Host ("`nQuerying Server: `"$ServerName`" for disconnected sessions under UserName: `"" + $UserName.ToUpper() + "`"...") -BackgroundColor Gray -ForegroundColor Black

        query user $UserName /server:$ServerName 2>&1 | foreach {  

            if ($_ -match "Active") {
                Write-Host "Active Sessions"
                $queryResults = ("`n$ServerName," + (($_.trim() -replace ' {2,}', ','))) | ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionName","SessionID","CurrentState","IdealTime","LogonTime"


                $queryResults | ft
                Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black

                $queryResults | foreach {
                    $Sessionl = $_.SessionID
                    $Serverl = $_.ServerName
                    Write-Host "Logging off"$_.username"from $serverl..." -ForegroundColor black -BackgroundColor Gray
                    sleep 2
                    logoff $Sessionl /server:$Serverl /v

                }


            }                
            elseif ($_ -match "Disc") {
                Write-Host "Disconnected Sessions"
                $queryResults = ("`n$ServerName," + (($_.trim() -replace ' {2,}', ','))) |  ConvertFrom-Csv -Delimiter "," -Header "ServerName","UserName","SessionID","CurrentState","IdealTime","LogonTime"

                $queryResults | ft
                Write-Host "Starting logoff procedure..." -BackgroundColor Gray -ForegroundColor Black

                $queryResults | foreach {
                    $Sessionl = $_.SessionID
                    $Serverl = $_.ServerName
                    Write-Host "Logging off"$_.username"from $serverl..."
                    sleep 2
                    logoff $Sessionl /server:$Serverl /v

                }
            }
            elseif ($_ -match "The RPC server is unavailable") {

                Write-Host "Unable to query the $ServerName, check for firewall settings on $ServerName!" -ForegroundColor White -BackgroundColor Red
            }
            elseif ($_ -match "No User exists for") {Write-Host "No user session exists"}

    }
}
else {

    Write-Host "`n`n`n$ServerName is Offline!" -BackgroundColor red -ForegroundColor white
    Write-Host "Error: Unable to connect to $ServerName!" -BackgroundColor red -ForegroundColor white
    Write-Host "Either the $ServerName is down or check for firewall settings on server $ServerName!" -BackgroundColor Yellow -ForegroundColor black
}





Read-Host "`n`nScript execution finished, press enter to exit!"

일부 샘플 출력.활성 세션의 경우:

연결이 끊긴 세션의 경우:

세션을 찾을 수 없는 경우:enter image description here 모든 AD 서버에 사용자 이름을 쿼리하고 연결되지 않은 세션만 로그오프하려면 이 솔루션도 확인하십시오.서버 연결 또는 쿼리 중 오류가 있었는지 여부도 스크립트를 통해 알 수 있습니다.

연결이 끊긴 RDP 세션을 검색하고 동시에 로그오프하는 파워셸

저는 제 코드가 더 쉽고 빠르게 작동할 것이라고 확신합니다.

    $logon_sessions = get-process -includeusername | Select-Object -Unique -Property UserName, si | ? { $_ -match "server" -and $_ -notmatch "admin" }

    foreach ($id in $logon_sessions.si) {
        logoff $id
    }

이것이 제가 생각해낸 것입니다. 여러개의 답을 합치는 것입니다.

#computer list below
$computers = (
'computer1.domain.local',
'computer2.domain.local'

)
 
foreach ($Computer in $computers) {

 Invoke-Command -ComputerName $Computer -ScriptBlock { 
  Write-Host '______  '$Env:Computername
  $usertocheck = 'SomeUserName'
$sessionID = ((quser | Where-Object { $_ -match $usertocheck }) -split ' +')[2]
 

If([string]::IsNullOrEmpty($sessionID)){            
    Write-Host -ForegroundColor Yellow  "User Not Found."           
} else {            
    write-host -ForegroundColor Green  'Logging off ' $usertocheck 'Session ID' $sessionID
    logoff $sessionID    
}

 }
 }

아래 간단한 스크립트는 동일한 컴퓨터에 있는 연결이 끊긴 모든 사용자를 로그오프합니다.

$hostname = hostname
if (Test-Connection -ComputerName $hostname -Quiet -Count 1){
    $result = query session /server:$hostname
    $rows = $result -split "`n" 
    foreach ($row in $rows) {   
        if ($row -NotMatch "services|console" -and $row -match "Disc") {
            $sessionusername = $row.Substring(19,20).Trim()
            $sessionid = $row.Substring(39,9).Trim()
            Write-Output "Logging Off RDP Disconnected Sessions User $sessionusername"#, $session[2], $session[3]"
            logoff $sessionid /server:$hostname
        }
    }
}

출력은

Logging Off RDP Disconnected Sessions User xyz

언급URL : https://stackoverflow.com/questions/18192746/powershell-log-off-remote-session

반응형