How to Log Off a Remote User Session in Batch Script
Sometimes, remote users leave their sessions open indefinitely, consuming valuable system resources or blocking others from connecting to the server. For IT administrators, being able to forcefully "kick" a session offline is a standard procedure. While you can do this via the Task Manager's "Users" tab, using the logoff command in a Batch script allows you to automate cleanup tasks (e.g., "Log off all disconnected sessions every night at 3 AM").
This guide explains how to identify and terminate remote sessions.
Why Force Logoffs?
- Stuck Sessions: Removing a user whose RDP window has frozen but the session is still "Active" on the server.
- Resource Reclaiming: Freeing up RAM and CPU cycles on a terminal server by removing idle users.
- Security: Ensuring that no open sessions remain on a sensitive machine after business hours.
The logoff command is built into all modern versions of Windows. The rwinsta (Reset Window Station) command is a related alternative that forcefully resets a session.
Method 1: Logoff by Session ID
The most reliable way to log off a user is by their Session ID (use quser or qwinsta to find this number first).
@echo off
setlocal
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)
:: Show current sessions first
echo [INFO] Current sessions:
echo -----------------------------------------
query user 2>nul
echo -----------------------------------------
echo.
set /p "ID=Enter Session ID to log off: "
if "%ID%"=="" (
echo [ERROR] No session ID entered.
pause
exit /b 1
)
:: Validate it's a number
echo %ID%| findstr /r "^[0-9][0-9]*$" >nul
if %errorlevel% neq 0 (
echo [ERROR] Session ID must be a number.
pause
exit /b 1
)
echo [WARNING] This will immediately terminate all programs in session %ID%.
set /p "CONFIRM=Proceed? (Y/N): "
if /i not "%CONFIRM%"=="Y" (
echo [INFO] Cancelled.
pause
exit /b 0
)
echo [PROCESS] Terminating Session ID %ID%...
logoff %ID% /v
if %errorlevel% equ 0 (
echo [SUCCESS] Session %ID% has been logged off.
) else (
echo [ERROR] Could not log off session %ID%.
echo [HELP] The session may not exist, or it may be session 0 (Services^).
)
pause
Method 2: Logoff by Session Name
If you know the session name (e.g., rdp-tcp#12), you can target that directly.
@echo off
setlocal
:: Check for admin rights
net session >nul 2>&1
if %errorlevel% neq 0 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)
set /p "SNAME=Enter session name (e.g., rdp-tcp#12): "
if "%SNAME%"=="" (
echo [ERROR] No session name entered.
pause
exit /b 1
)
echo [PROCESS] Ending session: "%SNAME%"...
logoff "%SNAME%"
if %errorlevel% equ 0 (
echo [SUCCESS] Session "%SNAME%" has been logged off.
) else (
echo [ERROR] Session "%SNAME%" not found or access denied.
)
pause
Creating a "Logoff Disconnected Users" Script
This professional script finds all sessions in the "Disconnected" state and offers to log them off, using the reliable whole-line approach rather than fragile column parsing.
@echo off
setlocal EnableDelayedExpansion
echo ============================================================
echo Stale Session Cleanup Tool
echo ============================================================
:: -----------------------------
:: 1. Check for admin rights
:: -----------------------------
net session >nul 2>&1
if errorlevel 1 (
echo [ERROR] Administrator privileges are required.
pause
exit /b 1
)
:: -----------------------------
:: 2. Verify there are sessions
:: -----------------------------
set "HAS_SESSIONS="
for /f %%A in ('query user 2^>nul') do (
set "HAS_SESSIONS=1"
goto :SessionsChecked
)
:SessionsChecked
if not defined HAS_SESSIONS (
echo [INFO] No user sessions found or query not supported.
echo ============================================================
pause
exit /b 0
)
:: -----------------------------
:: 3. Find disconnected sessions
:: -----------------------------
echo.
echo [PROCESS] Searching for disconnected sessions...
echo.
set "DISC_COUNT=0"
for /f "skip=1 tokens=*" %%s in ('query user 2^>nul') do (
echo %%s | findstr /i "Disc" >nul
if not errorlevel 1 (
echo [FOUND] %%s
set /a "DISC_COUNT+=1"
)
)
if !DISC_COUNT! equ 0 (
echo [OK] No disconnected sessions found. System is clean.
echo ============================================================
pause
exit /b 0
)
echo.
echo [INFO] Found !DISC_COUNT! disconnected session(s^).
echo.
:: -----------------------------
:: 4. Confirm before logoff
:: -----------------------------
set /p "CONFIRM=Log off all disconnected sessions? (Y/N): "
if /i not "!CONFIRM!"=="Y" (
echo [INFO] Cancelled. No sessions were terminated.
echo ============================================================
pause
exit /b 0
)
:: -----------------------------
:: 5. Clean up disconnected sessions
:: -----------------------------
echo.
echo [PROCESS] Cleaning up disconnected sessions...
powershell -NoProfile -Command ^
"query user | Select-Object -Skip 1 | ForEach-Object { ^
if ($_ -match 'Disc') { ^
$parts = ($_ -split '\s+') | Where-Object { $_ -ne '' }; ^
if ($parts.Count -ge 3) { ^
$user = $parts[0]; ^
$id = $parts[2]; ^
Write-Host (' Logging off: ' + $user + ' (Session ' + $id + ')'); ^
logoff $id 2>$null; ^
} ^
} ^
}"
:: -----------------------------
:: 6. Show remaining sessions
:: -----------------------------
echo.
echo [VERIFY] Remaining sessions:
query user 2>nul
if errorlevel 1 echo (no sessions remaining^)
echo ============================================================
pause
endlocal
Common Pitfalls and How to Avoid Them
Logging Off the Wrong ID
"Session ID 0" is the "Services" session on modern Windows (Session 0 Isolation). You cannot log off ID 0 with logoff. Attempting to do so will return "Access is denied."
Finding the Right ID
The output of query user shifts columns depending on whether a Session Name exists.
Solution:
For robust automation, use PowerShell regex parsing (as shown in the cleanup script) or Get-RDUserSession to reliably extract session IDs regardless of column alignment.
Advise your users that logging off a session immediately terminates all running programs without saving open documents. Always try to warn the user with msg first!
Best Practices for Session Termination
- Check Idle Time: Before logging someone off, check their "Idle Time" column in
quser. If it's only 5 minutes, they might be on a coffee break. If it's 5 days, they are gone. - Combine with 'Msg': Send a warning message:
msg %ID% "You will be logged off in 60 seconds."thentimeout /t 60 /nobreak >nulthenlogoff %ID%. - Scheduled Task: Set your cleanup script to run at 2 AM via Task Scheduler to ensure servers are fresh for the morning shift.
If a session is stuck in a "Closing" state, logoff might not work. In that case, you may need to kill the winlogon.exe process for that user or reboot the server.
Conclusion
Logging off a remote session via Batch script is a powerful administrative action that keeps your servers clean and performant. By leveraging the logoff command to programmatically remove stale connections, you prevent resource exhaustion and ensure that legitimate users can always connect. This professional practice maintains a disciplined and efficient computing environment, enforcing usage policies and maximizing uptime across your entire Windows infrastructure.