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.
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
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!
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
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>
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.
Essayez le Module PowerShell des services Terminal Server :
Get-TSSession -ComputerName comp1 -UserName user1 | Stop-TSSession -Force
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 {}
}
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'erreurselect -skip 1
supprime la ligne d'en-têteforeach
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 terminalJe 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:
Pour les sessions déconnectées:
si aucune session n'a été trouvée: 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
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.