使用query session和 logoff的批处理脚本无法从远程服务器登出用户

编程语言 2026-07-11

我正在尝试在多台Windows服务器上自动化应用更新。在更新运行之前,我需要从几台服务器登出所有用户(Active、Disconnected、Hung等),但不包括在当前机器上运行脚本的用户。

服务器是:

NRD01-A
NRD01-B
NRD02-A
NRD02-B

PowerShell在这些服务器上受限/被阻止,因此我必须使用批处理脚本。

思路是:

  • 使用 query session 来识别服务器上的所有会话
  • 使用 logoffreset session 注销每一个会话
  • 在执行脚本的这台机器上跳过当前脚本运行者的会话

然而,当我运行脚本时,服务器上没有注销任何用户。

下面是我写的批处理脚本:

for /f %%H in ('hostname') do set "CURRENT_SERVER=%%H"
set "CURRENT_USER=%USERNAME%"

setlocal EnableDelayedExpansion

set "SERVERS=NRD01-A NRD01-B NRD02-A NRD02-B"
set "RUNSERVER=%COMPUTERNAME%"
set "CURRENT_USER=%USERNAME%"

for /F "tokens=3" %%S in ('query session ^| findstr /R /C:" %CURRENT_USER% "') do set "MYSESSION=%%S"

for %%S in (%SERVERS%) do (

    for /f "skip=1 tokens=1,2,3,4" %%A in ('query session /server:%%S 2^>nul') do (

        set "USER=%%B"
        set "COL3=%%C"
        set "COL4=%%D"

        set "ID="

        if "!COL3!"=="Disc" set "ID=!COL4!"
        if not "!COL3!"=="Disc" set "ID=!COL3!"

        if not "!ID!"=="" (

            if /I "!USER!"=="!CURRENT_USER!" if /I "%%S"=="!RUNSERVER!" if "!ID!"=="!MYSESSION!" (
                REM Protect script runner
            ) else (

                logoff !ID! /server:%%S >nul 2>&1
                reset session !ID! /server:%%S >nul 2>&1

            )

        )

    )

)

for %%S in (%SERVERS%) do (

    for /f "skip=1 tokens=2" %%A in ('query session /server:%%S 2^>nul ^| findstr /V "services console rdp-tcp"') do (

        set "USER=%%A"

        if not "!USER!"=="" (

            set "SKIP=0"

            if /I "!USER!"=="!CURRENT_USER!" (
                if /I "%%S"=="!RUNSERVER!" set "SKIP=1"
            )

            if "!SKIP!"=="0" (

                logoff %%A /server:%%S >nul 2>&1
                rwinsta %%A /server:%%S >nul 2>&1

            )

        )

    )

)


Expected behavior:

All sessions on all listed servers should be logged off

The session of the user running the script on the current machine should be skipped

Actual behavior:

The script runs but no users are logged out from the servers

Questions:

Why is this script not logging out users from the remote servers?

Is there an issue with how the session IDs are parsed from query session?

Is there a more reliable way to log off all sessions from multiple servers using only batch (no PowerShell)?

Any suggestions or improvements would be appreciated.

解决方案

我没有访问到一个能够让query session 返回值的系统。Google给了我一个典型返回值的简短示例:

 SESSIONNAME USERNAME ID STATE  TYPE        DEVICE
 >console    Admin      0 active wdcon
 rdp-tcp#1   User1      1 active wdtshare
 rdp-tcp                2 listen wdtshare

因此我会研究一些可能性:

在你的脚本中,你使用

        set "USER=%%B"
        set "COL3=%%C"
        set "COL4=%%D"

        set "ID="

        if "!COL3!"=="Disc" set "ID=!COL4!"
        if not "!COL3!"=="Disc" set "ID=!COL3!"

我会非常仔细地看这个。我建议 col3 实际上是 IDcol4STATE,其中可能缺少 USER。 (在这里对你的查询结果进行一个模糊化的部分清单编辑可能有帮助)

我也会查看 Using Boolean 这可能有助于简化代码,例如用 if defined ID 代替 if not "!ID!"=="",并将 skip 设为 nothingsomething 可能更简单。

我遵循这样一个系统:仅在一个块内的 var 发生变化时才使用 !var!;否则使用 %var%。这起到直观提示的作用:“我预计这会变化” 与 “这应该是静态”。例如,你在一个块内设置了 ID COL3 COL4,因此访问这些值时应该是 !var!,但 CURRENT_USER 在该块内并不变化,因此应当按 %CURRENT_USER% 访问。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章