Skip to content

How to Log Off a Remote User Session in Batch Script

Learn how to automate remote session termination in Windows using Batch scripts to forcefully log off disconnected, idle, or stuck RDP sessions by Session ID or name.

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.

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.

Best Practices for Session Termination

  1. 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.
  2. Combine with 'Msg': Send a warning message: msg %ID% "You will be logged off in 60 seconds." then timeout /t 60 /nobreak >nul then logoff %ID%.
  3. Scheduled Task: Set your cleanup script to run at 2 AM via Task Scheduler to ensure servers are fresh for the morning shift.

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.

Navigation