web-dev-qa-db-fra.com

Déconnexion de Powershell d'une session à distance

J'essaie de formuler une commande Powershell pour déconnecter un utilisateur à distance. Nous avons un serveur de terminal avec un programme très instable qui verrouille parfois les sessions. Nous devons déconnecter un utilisateur à distance, mais j'essaie d'écrire une déclaration Powershell qui déconnectera la personne qui a exécuté le script. J'ai cherché sur Google et trouvé cette commande:

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

Cependant, la commande renvoie "fonction incorrecte". Je peux exécuter avec succès d'autres commandes entre crochets, telles que Get-Process.

L'idée est pour moi de mettre cela dans un script que les utilisateurs peuvent exécuter pour se déconnecter du serveur (car lors du verrouillage, ils ne peuvent pas accéder au menu Démarrer ni à ALT + CTRL + FIN pour le faire via l'interface graphique).

Le flux serait le suivant: Bob se connecte à MyServer via RDP mais sa session est bloquée. Sur son bureau local, il peut exécuter MyScript (contenant une commande similaire à celle décrite ci-dessus) qui déconnectera sa session sur MyServer.

29
jlacroix

Il est peut-être surprenant que vous puissiez déconnecter les utilisateurs avec la commande 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.

L'ID de session peut être déterminé à l'aide des commandes qwinsta (query session) ou quser (query user) (voir ici ):

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

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

logoff $session /server:$server
45
Ansgar Wiechers

Voici une excellente solution scriptée pour déconnecter les gens à distance ou localement. J'utilise qwinsta pour obtenir des informations sur la session et créer un tableau à partir de la sortie donnée. Il est ainsi très facile de parcourir chaque entrée et de ne déconnecter que les utilisateurs réels, et non le programme d’écoute ou le programme d’écoute RDP lui-même, qui génère généralement une erreur d’accès refusé de toute façon.

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

Dans la première ligne de ce script, donnez à $ serverName la valeur appropriée ou l'hôte local s'il est exécuté localement. J'utilise ce script pour donner un coup de pied aux utilisateurs avant qu'un processus automatisé ne tente de déplacer certains dossiers. Empêche les erreurs "fichier en cours d'utilisation" pour moi. Autre remarque, ce script devra être exécuté en tant qu'administrateur. Dans le cas contraire, vous ne pourrez pas y accéder en essayant de déconnecter quelqu'un. J'espère que cela t'aides!

12
Jason Slobotski

Ajouter des commandes DOS simples, si quelqu'un est si enclin. Oui, cela fonctionne toujours pour Win 8 et Server 2008 + Server 2012.

Query session /server:Server100

Reviendra:

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

Et pour vous déconnecter d'une session, utilisez:

Reset session 3 /server:Server100
11
user4317867

Ceci est oldschool et précède PowerShell, mais j’ai utilisé le combo qwinsta/rwinsta for YEARS pour vous déconnecter à distance des sessions RDP obsolètes. Il est intégré au moins à Windows XP et à la version ultérieure (éventuellement antérieure).

Déterminez l'ID de session:

qwinsta /SERVER:<NAME>

Supprimer la session en question:

rwinsta <SESSION_ID> /SERVER:<NAME>
7
Joshua McKinnon

Vous pouvez utiliser Invoke-RDUserLogoff

Exemple de déconnexion d'utilisateurs Active Directory d'une unité d'organisation spécifique:

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

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

À la fin du tuyau, si vous essayez d'utiliser uniquement foreach (%), un seul utilisateur sera connecté. Mais en utilisant cette combinaison de foreach et pipe:

| % {$ _ | commande}

fonctionnera comme prévu.

Ps. Exécuter comme Adm.

4
Gauss

Essayez le Module PowerShell des services Terminal Server :

Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force
4
Shay Levy

J'ai modifié la réponse de Casey pour ne déconnecter que les sessions déconnectées en procédant comme suit:

   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 {}
    }
3
O.C.

Déconnectez tous les utilisateurs d'une machine:

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

Détails:

  • try/catch est utilisé lorsqu'il n'y a aucun utilisateur sur le serveur et que query renvoie une erreur. Cependant, vous pouvez supprimer la partie 2>&1 et supprimer le try/catch si cela ne vous dérange pas de voir la chaîne d'erreur
  • select -skip 1 supprime la ligne d'en-tête
  • le foreach intérieur déconnecte chaque utilisateur
  • ($_ -split "\s+") divise la chaîne en un tableau contenant uniquement des éléments de texte
  • [-6] index obtient l'ID de session et est la 6ème chaîne comptant à partir du revers du tableau, vous devez le faire car la sortie query aura 8 ou 9 éléments selon que les utilisateurs sont connectés ou déconnectés de la session de terminal
2
cmcginty

Je suis sûr que mon code sera plus facile et fonctionne plus rapidement.

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

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

Le script ci-dessous fonctionnera bien pour les sessions actives et déconnectées tant que l'utilisateur aura le droit d'exécuter la commande de déconnexion à distance. Tout ce que vous avez à faire est de changer le nom de serveur de "YourServerName" sur la 4ème ligne.

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!"

Quelques exemples de sorties. Pour session active:  enter image description here

Pour les sessions déconnectées:  enter image description here

si aucune session n'a été trouvée:  enter image description here Consultez cette solution également pour interroger tous les serveurs AD sur votre nom d'utilisateur et ne déconnecter que les sessions déconnectées. Le script vous indiquera également s'il y a eu une erreur de connexion ou d'interrogation du serveur.

Powershell pour découvrir une session RDP déconnectée et se déconnecter en même temps

0
LT-

Puisque nous sommes dans la zone PowerShell, il est particulièrement utile de pouvoir renvoyer un objet PowerShell approprié ...

Personnellement, j'aime bien cette méthode d'analyse, pour la concision:

((quser) -replace '^>', '') -replace '\s{2,}', ',' | ConvertFrom-Csv

Remarque: ceci ne représente pas les utilisateurs déconnectés ("disc"), mais fonctionne bien si vous voulez juste obtenir une liste rapide des utilisateurs et ne vous souciez pas du reste des informations. je voulais juste une liste et je ne me souciais pas de savoir s'ils étaient actuellement déconnectés.

Si vous vous souciez du reste des données, c'est un peu plus complexe:

(((quser) -replace '^>', '') -replace '\s{2,}', ',').Trim() | ForEach-Object {
    if ($_.Split(',').Count -eq 5) {
        Write-Output ($_ -replace '(^[^,]+)', '$1,')
    } else {
        Write-Output $_
    }
} | ConvertFrom-Csv

Je vais un peu plus loin et vous donne un objet très propre sur mon blog.

0
VertigoRay