如何实现局域网设备批量一键关机
[!TIP]
这篇文章的实现方式是有可能出问题的,比如无法在dhcp环境下使用、net use连接不到,所以不建议在客户端较多的情况下使用该方法,针对这情况,已经有了基于C/S架构的方案,后续会加到此文章中
摘要:现在有些教室、考场环境需要实现一键关机的情况,但是自身软件又无法实现此功能且因其他软件有特征触发告警导致无法使用其他软件,此文章使用windows自带的用户策略实现同局域网批量管理的操作
Win 7
这里以Win 10为主,Win 7步骤跟Win 10差不多
Win 10
1、创建统一的管理员账号
按win+r打开运行,输入compmgmt.msc并回车,然后进入系统工具→本地用户和组→用户,然后在页面右键点击新用户

然后创建新用户,这边是
用户名:shutdownadmin
密码:123456
记得取消“用户下次登录时必须更改密码”

2、将账号加入Administrators
还是在刚刚这个里面,在本地用户和组→组里面,找到Administrators这个组,双击打开,然后点击添加→高级→立即查找找到刚刚创建的shutdownadmin用户,然后确定即可,最后应用即可

也可以使用管理员CMD命令的方式添加(shutdownadmin为你刚刚创建的用户名)
net localgroup Administrators shutdownadmin /add
看到
The command completed successfully.
即为成功
3、设置“远程强制关机”权限
按win+r打开运行,输入secpol.msc并回车,然后进入本地策略→用户权限分配,在页面右侧的列表中找到从远程系统强制关机/Force shutdown from a remote system,双击打开后确保Administrators在其中,若不在,则点击添加用户或组自行添加即可,具体操作与上一步类似

同样在该页面,找到从网络访问此计算机,检查Administrators是否在其中,不在则同样自行添加
然后继续找拒绝从网络访问这台计算机,如果为空则不管,若包含Administrators,双击打开并将其删除后点击应用
4、配置Windows防火墙
按win+r打开运行,输入wf.msc并回车,点击入站规则,找到下图的这些规则启动即可

5、处理 UAC 远程限制
按win+r打开运行,输入regedit并回车,找到
HKEY_LOCAL_MACHINE
└─ SOFTWARE
└─ Microsoft
└─ Windows
└─ CurrentVersion
└─ Policies
└─ System
点击System,在右侧找LocalAccountTokenFilterPolicy,如果有,双击打开,将值设置为1(十六进制)
如果没有,右键空白处新建→DWORD (32 位) 值,名字设置为LocalAccountTokenFilterPolicy,然后双击打开,将值设置为1(十六进制),确定即可


6、重启Win 10
配置完后,按win+r打开运行,输入cmd并回车,输入
shutdown /r /t 0
让策略和相关服务重新加载
7、到管理机测试连通情况
首先到需要远程关机的主机上,按win+r打开运行,输入cmd并回车,输入ipconfig,找到wifi/以太网里面的ipv4地址记住,我这里是192.168.85.128

然后来到管理端电脑,同样按win+r打开运行,输入cmd并回车,输入(记得将ip改为你实际需要控制远程关机的主机的ip)
net use \\192.168.85.128\ipc$ /user:192.168.85.128\shutdownadmin
系统会让你输入密码,如果成功,会出现类似:
The command completed successfully.
8、在管理机测试远程关机
在管理端电脑上,按win+r打开运行,输入cmd并回车,输入
shutdown /s /m \\192.168.85.128 /t 3
如果成功,ip为192.168.85.128的电脑会在3秒后关机
服务端批处理客户端关机脚本(静态ip)
[!WARNING]
当需要远程控制关机的主机ip为静态配置时,才使用bat批处理脚本控制,若ip为dhcp分配,请跳转至···
假设有四个主机,其ip为
192.168.85.128
192.168.85.129
192.168.85.130
192.168.85.131
在管理端主机上,新建targets.txt,将上述四个ip地址输入进去
然后创建shutdown_all.bat文件,内容为
@echo off
echo ==============================
echo 批量关闭 Win10 虚拟机
echo ==============================
setlocal
for /f "usebackq tokens=* delims=" %%i in ("targets.txt") do (
echo.
echo ===== %%i =====
net use \\%%i\ipc$ /user:%%i\shutdownadmin 123456 /persistent:no
if errorlevel 1 (
echo [失败] %%i 认证失败
) else (
echo [成功] %%i 认证成功,正在关机...
start shutdown /s /m \\%%i /t 3
net use \\%%i\ipc$ /delete /y >nul 2>&1
)
)
endlocal
echo.
echo 所有关机命令已经发送。
pause
该脚本会读取targets.txt并依次发送关机指令
客户端一键配置脚本
上述操作很多,如果在主机设备数量多的情况下,一台台去配肯定不现实,这里研究了一个脚本,一键将上述操作配置完成
创建setup_remote_shutdown.bat,内容如下,然后在需要配置电脑上以管理员身份运行一次即可
@echo off
chcp 65001 >nul
setlocal EnableExtensions EnableDelayedExpansion
title 远程关机环境自动配置
set "USERNAME=shutdownadmin"
set "PASSWORD=123456"
set "TMPDIR=C:\Windows\Temp"
set "CFG=%TMPDIR%\rs.cfg"
set "CFG_A=%TMPDIR%\rs_ansi.cfg"
set "CFG_NEW=%TMPDIR%\rs_new.cfg"
set "SDB=%TMPDIR%\rs.sdb"
set "FAILED=0"
echo ========================================
echo Windows 远程关机环境自动配置
echo ========================================
echo.
net session >nul 2>&1
if not %errorlevel%==0 (
echo [错误] 请使用管理员身份运行此脚本。
pause
exit /b 1
)
:: ---------- 检测 PowerShell 绝对路径 ----------
set "PS_EXE="
if exist "%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" set "PS_EXE=%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe"
if not defined PS_EXE if exist "%SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe" set "PS_EXE=%SystemRoot%\Sysnative\WindowsPowerShell\v1.0\powershell.exe"
if not defined PS_EXE if exist "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" set "PS_EXE=C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
if not defined PS_EXE if exist "C:\Windows\Sysnative\WindowsPowerShell\v1.0\powershell.exe" set "PS_EXE=C:\Windows\Sysnative\WindowsPowerShell\v1.0\powershell.exe"
if not defined PS_EXE if exist "C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe" set "PS_EXE=C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe"
if defined PS_EXE (
echo [信息] 使用 PowerShell 路径:!PS_EXE!
) else (
echo [信息] 未找到 PowerShell,将使用纯批处理方案。
)
echo.
:: ========================================
:: 1. 创建/更新统一管理员账号
:: ========================================
echo [1/6] 创建或更新 %USERNAME% 用户...
net user %USERNAME% "%PASSWORD%" /add /passwordchg:no /logonpasswordchg:no >nul 2>&1
if errorlevel 1 (
net user %USERNAME% "%PASSWORD%" /passwordchg:no /logonpasswordchg:no >nul 2>&1
if errorlevel 1 (
echo [错误] 创建/更新用户失败。
set "FAILED=1"
) else (
echo [成功] 用户已更新。
)
) else (
echo [成功] 用户已创建。
)
wmic useraccount where "Name='%USERNAME%' and LocalAccount=True" set PasswordExpires=false >nul 2>&1
:: ========================================
:: 2. 加入 Administrators
:: ========================================
echo.
echo [2/6] 将 %USERNAME% 加入 Administrators...
net localgroup Administrators %USERNAME% /add >nul 2>&1
if errorlevel 1 (
net localgroup Administrators | findstr /i /c:"%USERNAME%" >nul
if errorlevel 1 (
echo [错误] 加入 Administrators 失败。
set "FAILED=1"
) else (
echo [提示] 用户已在 Administrators 组中。
)
) else (
echo [成功] 已加入 Administrators。
)
:: ========================================
:: 3. 配置远程关机与网络访问权限
:: ========================================
echo.
echo [3/6] 配置远程关机与网络访问权限...
secedit /export /cfg "%CFG%" /areas USER_RIGHTS >nul 2>&1
if not exist "%CFG%" (
echo [错误] 导出安全策略失败。
set "FAILED=1"
goto :STEP4
)
set "PS_OK=0"
if defined PS_EXE (
"!PS_EXE!" -NoProfile -ExecutionPolicy Bypass -Command "$p='%CFG%'; $c=Get-Content $p; if ($c -match '^SeRemoteShutdownPrivilege\s*=') { $c = $c -replace '^SeRemoteShutdownPrivilege\s*=.*$', 'SeRemoteShutdownPrivilege = *S-1-5-32-544' } else { $c += 'SeRemoteShutdownPrivilege = *S-1-5-32-544' }; $line = ($c | Where-Object { $_ -match '^SeNetworkLogonRight\s*=' }) -join ''; if ($line) { $parts = ($line -replace '^SeNetworkLogonRight\s*=\s*', '') -split '\s*,\s*' | Where-Object { $_ -ne '' }; if ($parts -notcontains '*S-1-5-32-544') { $parts += '*S-1-5-32-544' }; $c = $c -replace '^SeNetworkLogonRight\s*=.*$', ('SeNetworkLogonRight = ' + ($parts -join ',')) } else { $c += 'SeNetworkLogonRight = *S-1-5-32-544' }; $line = ($c | Where-Object { $_ -match '^SeDenyNetworkLogonRight\s*=' }) -join ''; if ($line) { $parts = ($line -replace '^SeDenyNetworkLogonRight\s*=\s*', '') -split '\s*,\s*' | Where-Object { $_ -ne '' -and $_ -ne '*S-1-5-32-544' }; if ($parts) { $c = $c -replace '^SeDenyNetworkLogonRight\s*=.*$', ('SeDenyNetworkLogonRight = ' + ($parts -join ',')) } else { $c = $c -replace '^SeDenyNetworkLogonRight\s*=.*$', 'SeDenyNetworkLogonRight =' } } else { $c += 'SeDenyNetworkLogonRight =' }; Set-Content $p $c -Encoding Unicode"
if not errorlevel 1 set "PS_OK=1"
)
if "!PS_OK!"=="1" (
secedit /configure /db "%SDB%" /cfg "%CFG%" /areas USER_RIGHTS >nul 2>&1
if errorlevel 1 (
echo [错误] 应用安全策略失败。
set "FAILED=1"
) else (
echo [成功] 远程关机与网络访问权限已配置。
)
) else (
echo [提示] PowerShell 方式不可用,改用批处理方式...
more < "%CFG%" > "%CFG_A%"
if not exist "%CFG_A%" (
echo [错误] 转换 cfg 到 ANSI 失败。
set "FAILED=1"
goto :STEP4
)
findstr /v /b /c:"SeRemoteShutdownPrivilege" "%CFG_A%" > "%CFG_NEW%"
>>"%CFG_NEW%" echo SeRemoteShutdownPrivilege = *S-1-5-32-544
set "NL_VALUE="
for /f "tokens=1,* delims==" %%a in ('findstr /b /c:"SeNetworkLogonRight" "%CFG_A%"') do set "NL_VALUE=%%b"
if defined NL_VALUE (
set "NL_VALUE=!NL_VALUE: =!"
echo !NL_VALUE! | findstr /c:"*S-1-5-32-544" >nul
if errorlevel 1 set "NL_VALUE=!NL_VALUE!,*S-1-5-32-544"
) else (
set "NL_VALUE=*S-1-5-32-544"
)
findstr /v /b /c:"SeNetworkLogonRight" "%CFG_NEW%" > "%CFG_NEW%.tmp"
move /y "%CFG_NEW%.tmp" "%CFG_NEW%" >nul
>>"%CFG_NEW%" echo SeNetworkLogonRight = !NL_VALUE!
set "DNL_VALUE="
for /f "tokens=1,* delims==" %%a in ('findstr /b /c:"SeDenyNetworkLogonRight" "%CFG_A%"') do set "DNL_VALUE=%%b"
if defined DNL_VALUE (
set "DNL_VALUE=!DNL_VALUE: =!"
set "DNL_VALUE=!DNL_VALUE:*S-1-5-32-544=!"
if "!DNL_VALUE:~0,1!"=="," set "DNL_VALUE=!DNL_VALUE:~1!"
if defined DNL_VALUE if "!DNL_VALUE:~-1!"=="," set "DNL_VALUE=!DNL_VALUE:~0,-1!"
)
findstr /v /b /c:"SeDenyNetworkLogonRight" "%CFG_NEW%" > "%CFG_NEW%.tmp"
move /y "%CFG_NEW%.tmp" "%CFG_NEW%" >nul
>>"%CFG_NEW%" echo SeDenyNetworkLogonRight = !DNL_VALUE!
secedit /configure /db "%SDB%" /cfg "%CFG_NEW%" /areas USER_RIGHTS >nul 2>&1
if errorlevel 1 (
echo [错误] 应用安全策略失败。
set "FAILED=1"
) else (
echo [成功] 远程关机与网络访问权限已配置。
)
)
:STEP4
:: ========================================
:: 4. 开启防火墙相关规则
:: ========================================
echo.
echo [4/6] 开启 Windows 防火墙相关规则...
netsh advfirewall firewall set rule group="文件和打印机共享" new enable=Yes >nul 2>&1
if errorlevel 1 (
netsh advfirewall firewall set rule group="File and Printer Sharing" new enable=Yes >nul 2>&1
if errorlevel 1 (
echo [提示] 未找到防火墙组 文件和打印机共享 / File and Printer Sharing,已跳过。
) else (
echo [成功] 已开启防火墙组 File and Printer Sharing
)
) else (
echo [成功] 已开启防火墙组 文件和打印机共享
)
netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=Yes >nul 2>&1
if errorlevel 1 (
netsh advfirewall firewall set rule group="Windows Management Instrumentation" new enable=Yes >nul 2>&1
if errorlevel 1 (
echo [提示] 未找到防火墙组 Windows Management Instrumentation,已跳过。
) else (
echo [成功] 已开启防火墙组 Windows Management Instrumentation
)
) else (
echo [成功] 已开启防火墙组 Windows Management Instrumentation (WMI)
)
netsh advfirewall firewall set rule group="远程服务管理" new enable=Yes >nul 2>&1
if errorlevel 1 (
netsh advfirewall firewall set rule group="Remote Service Management" new enable=Yes >nul 2>&1
if errorlevel 1 (
echo [提示] 未找到防火墙组 远程服务管理 / Remote Service Management,已跳过。
) else (
echo [成功] 已开启防火墙组 Remote Service Management
)
) else (
echo [成功] 已开启防火墙组 远程服务管理
)
netsh advfirewall firewall set rule group="远程事件日志管理" new enable=Yes >nul 2>&1
if errorlevel 1 (
netsh advfirewall firewall set rule group="Remote Event Log Management" new enable=Yes >nul 2>&1
if errorlevel 1 (
echo [提示] 未找到防火墙组 远程事件日志管理 / Remote Event Log Management,已跳过。
) else (
echo [成功] 已开启防火墙组 Remote Event Log Management
)
) else (
echo [成功] 已开启防火墙组 远程事件日志管理
)
:: ========================================
:: 5. 配置 UAC 远程限制
:: ========================================
echo.
echo [5/6] 配置 UAC 远程限制...
set "UAC_OK=0"
if defined PS_EXE (
"!PS_EXE!" -NoProfile -ExecutionPolicy Bypass -Command "try { New-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'LocalAccountTokenFilterPolicy' -Value 1 -PropertyType DWord -Force -ErrorAction Stop | Out-Null; $v = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'LocalAccountTokenFilterPolicy' -ErrorAction Stop).LocalAccountTokenFilterPolicy; if ($v -eq 1) { exit 0 } else { exit 1 } } catch { exit 1 }"
if not errorlevel 1 set "UAC_OK=1"
)
if "!UAC_OK!"=="0" (
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f /reg:64 >nul 2>&1
if errorlevel 1 reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /t REG_DWORD /d 1 /f >nul 2>&1
)
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy /reg:64 2>nul | findstr /c:"0x1" >nul
if errorlevel 1 (
reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v LocalAccountTokenFilterPolicy 2>nul | findstr /c:"0x1" >nul
if errorlevel 1 (
echo [错误] LocalAccountTokenFilterPolicy 写入后验证失败。
set "FAILED=1"
) else (
echo [成功] LocalAccountTokenFilterPolicy 已设置为 1。
)
) else (
echo [成功] LocalAccountTokenFilterPolicy 已设置为 1。
)
:: ========================================
:: 最终处理
:: ========================================
echo.
if "!FAILED!"=="1" (
echo ========================================
echo 配置过程中存在失败项
echo ========================================
echo 未执行重启。请根据上面的错误检查后重试。
echo 按任意键退出。
pause >nul
exit /b 1
)
echo [6/6] 刷新安全策略...
gpupdate /force >nul
del "%CFG%" >nul 2>&1
del "%CFG_A%" >nul 2>&1
del "%CFG_NEW%" >nul 2>&1
del "%CFG_NEW%.tmp" >nul 2>&1
del "%SDB%" >nul 2>&1
echo.
echo ========================================
echo 配置完成
echo ========================================
echo 用户名:%USERNAME%
echo 密码:%PASSWORD%
echo.
echo 系统将在 10 秒后重启。
echo 重启后即可进行远程关机测试。
echo.
shutdown /r /t 10
echo 按任意键退出。
pause >nul
exit /b 0