From 2747b69b561aee7ebab5cdc682514b39a3749569 Mon Sep 17 00:00:00 2001 From: Agent Date: Fri, 20 Mar 2026 06:57:29 +0800 Subject: [PATCH] =?UTF-8?q?=E7=A7=BB=E9=99=A4=20Releases=20=E5=92=8C=20Tes?= =?UTF-8?q?t=20=E7=9B=AE=E5=BD=95=EF=BC=88=E6=8C=89=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=8F=AA=E5=90=8C=E6=AD=A5=20Code=20=E5=86=85=E5=AE=B9?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Releases/remote-volume-monitor-v1.0.zip | Bin 20307 -> 0 bytes Releases/remote-volume-monitor-v1.0/README.md | 181 ------ .../config/config.ini | 28 - .../docs/部署检查清单_远程音量控制.md | 254 -------- .../docs/音量控制方案说明.md | 222 ------- .../requirements.txt | 38 -- .../scripts/启动监控.bat | 39 -- .../src/remote_volume_monitor.py | 570 ------------------ .../tools/README.md | 62 -- .../remote-volume-monitor-v1.0/快速开始.md | 139 ----- .../版本说明_V1.0.md | 181 ------ Test/Cases/测试用例_远程音量控制.md | 343 ----------- Test/Scripts/test_rdp_detection.py | 229 ------- Test/Scripts/test_rdp_disconnect.py | 144 ----- 14 files changed, 2430 deletions(-) delete mode 100644 Releases/remote-volume-monitor-v1.0.zip delete mode 100644 Releases/remote-volume-monitor-v1.0/README.md delete mode 100644 Releases/remote-volume-monitor-v1.0/config/config.ini delete mode 100644 Releases/remote-volume-monitor-v1.0/docs/部署检查清单_远程音量控制.md delete mode 100644 Releases/remote-volume-monitor-v1.0/docs/音量控制方案说明.md delete mode 100644 Releases/remote-volume-monitor-v1.0/requirements.txt delete mode 100644 Releases/remote-volume-monitor-v1.0/scripts/启动监控.bat delete mode 100644 Releases/remote-volume-monitor-v1.0/src/remote_volume_monitor.py delete mode 100644 Releases/remote-volume-monitor-v1.0/tools/README.md delete mode 100644 Releases/remote-volume-monitor-v1.0/快速开始.md delete mode 100644 Releases/remote-volume-monitor-v1.0/版本说明_V1.0.md delete mode 100644 Test/Cases/测试用例_远程音量控制.md delete mode 100644 Test/Scripts/test_rdp_detection.py delete mode 100644 Test/Scripts/test_rdp_disconnect.py diff --git a/Releases/remote-volume-monitor-v1.0.zip b/Releases/remote-volume-monitor-v1.0.zip deleted file mode 100644 index f2ce563b40b90adb2136d8d03189af6b438c7d36..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20307 zcmb5VW0WXivMk!RZQC|>+qP}nwr%%r+qP}nw!3%Z?wL6c_pWzl&a1VmR{e_nQIQ!@ znfb{}0fRsR{NrNGHq-v+%YQwv0dN2uO>FF(O=w;1tX*tOXl?9lEu8HfXVFUFXyV{v z@i(Z6t+NxIv%B;E9poQ@{*NFjiqo>2zYuzEm8z1ps5XNMl%HWe50@lW;Dhy%q()i} zL;`ZNRS6|>IF#q)69|3+hRCn2Tf1ALuRdRfu`LDQO^)rcOa0;k>Zu#7^$`N|gj#|MEsCg=>6wf0D1RV4iO^(O)H-Xtih zZ`rFY)>(&jw^nH5#^{z>{Bg@SN4fn4X?3UZzU{n|yvi|%|5bdID2~k+kIoe52cyH~ zB>L_t-I-<=`)$X-Ug^g~BnT0thvw*w=S7iF>j56Tk#dv+Pw*_v9I{foJWF#mzM|G*|J)2K@O%UsRB%%%AsVgD-x zorSH%KdJkVDF3+s59+!k%18kzpoG4@s%e}5&NmRAD-pp*qh-P zMJ?1=749er7BrFAgYpsB@X5Tx&0P5{s0Kb&m73<1`^tOE*$Te_yI5hp8H2P<%UudD zYdSllouoZnW3$%o;;0zlduDx7{pzJT#Uu)o1l7pZCW`%WDkwVytp z_)CSX<>aL1_%Ro4#>*Et_G4p@5VTuS?nS-LN|Y^AhpQ;v!>|6rd~Yu}=2`o#=>@FJ z+|skf79$?6VWG478n~`s(S!~mX)3rD5&{NO2tujy(&7`_FykwpRp$;VS9%RG3%|wK zff0x%BUExmspt(=L<(n)oM{94dYP`JaT(c%=qy2cmhk2%l0pr-brY_p z&AK@dak8==`p@T%s^ICO9ShD8yudhZQ-Pr*3spx{5uN2<;n(O@9uiEkli$j!np$2D z1HY;OdI0{bY(f01Y-OvQyL^EF0H{F%08st=kAK`-dG4Qg+~t2<8bxPg{O_t(j_S57 zwi-guZYc*+#S+&85Me~2cz0PMc=$$?Zg3>&3z<5r?xe2Z0<{pq_bAyXhrbeZT>x2~ zYZgef-(6=Dx0ze5d&tbXh9R(w%Jala#{0>X_v17UJmXon8xrani9Y|Nlf+mWiG_K1 z45N6rqpsSRH5)Te4r(ajNSx(NClxmDt##&f)%JCRI0afdT&|nqZ@javq*Ri;+ZkF@ z*T<_-d6Kf}k@?-zBovW^5@%klUUnWHZf6VM`+8x3%;cbc88pi!&?>RMpV zs|@jD_xHx$l29P)L0*Ua`m~Knj4nJSvQ`}zekCDhB`QBnXprZcQ$NUTKI(Dy- zFRrqYJ#(c^5K*H*c$R_k$as>mJ^H@AH6zc^hB-N)x;1NN)bZBO7GI5B1KAVcA3O&8O8S+2fADH2F zDdy!Z(HA6oP)2R0{PJIk@Gv-OKD(Gt9~m#0vp)fkfl=^Lu$F2BBs_eCORmy%;=o>q zOqOrHCekbuS*Vz;HW|F^C`tG?hU0Z_?Fwz40ie80nFG|+EAy^GjsaOFGVxW;)v=N? zy7}RsBUe+|T_|qW$KBLx8xz<&r3@iPM0*l#$2ow+C=U90Z2d5&PhImf(a$==OSq_5 zE3=P_v7RK+i3NJi+s0&7)H957(;q_xpseH$(=t-;!zoH2$Yyr4n6s$?@0oS!?*?sp zvVPrEO@r!kxk}>Scjf(IP%&z0aA(#m1M0j_to3P%0h2ZCB`qW}TI7-8j`FCq5>H&# zXq`>XK$;_x6OsNWJQkv0pR$F=_QXYA0ZQ8EJE9ZB^8i9|Q+!r$ZETNZu=;5R04-VSn?)`NuNlde z2}N|>)QaE@s?9B=$}z@!zNs!+hSHPLNhD{7m3;|A$-Jz9`%uN@t@ z0_&`G7riK7=NZtA|BbyU@*8Y|w%@)!RztAhhGb!NG?Rm2(`L+ibA+u(R|yA4G8=SZ z!KE@CRNO|O6Ep=aQ38+TgO`G4@w=XFW6jn&irTTY;d{j4kRgQ3cf|)g_^Nt?i%i--jS36oKwXqQ@`)754 zE+z92Z)%P#R29`5P^x7h^o^W21bJY?1cwO)zy?I&^6≪aZI3jmfPo!b@x`T8$j; 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 SzA-Qe0%0L=jr$pQ5Dx&2_F{kl diff --git a/Releases/remote-volume-monitor-v1.0/README.md b/Releases/remote-volume-monitor-v1.0/README.md deleted file mode 100644 index fc857e5..0000000 --- a/Releases/remote-volume-monitor-v1.0/README.md +++ /dev/null @@ -1,181 +0,0 @@ -# 远程音量监控工具 V1.0 - -Windows 远程连接音量自动调节器 - 检测到 RDP 远程连接时自动调整系统音量 - ---- - -## 🚀 快速开始 - -### 1. 安装依赖工具(推荐) - -下载 nircmd.exe 放到 `tools` 文件夹: -- 64 位:https://www.nirsoft.net/utils/nircmd-x64.zip -- 32 位:https://www.nirsoft.net/utils/nircmd.zip - -解压后将 `nircmd.exe` 复制到 `tools\` 目录 - -### 2. 运行程序 - -**方式 1:使用启动脚本** -```bat -scripts\启动监控.bat -``` - -**方式 2:直接运行** -```bat -python src\remote_volume_monitor.py -``` - -**方式 3:测试模式** -```bat -python src\remote_volume_monitor.py --test -``` - ---- - -## 📋 功能特性 - -- ✅ 自动检测 RDP 远程连接/断开 -- ✅ 连接时自动降低音量(默认 30%) -- ✅ 断开时自动恢复音量(默认 80%) -- ✅ 零第三方 Python 依赖 -- ✅ 支持 nircmd/Core Audio/PowerShell 多种方案 -- ✅ 配置文件可自定义 -- ✅ 后台服务模式 - ---- - -## ⚙️ 配置说明 - -编辑 `config\config.ini`: - -```ini -[volume] -# 远程连接时的音量 (0-100) -remote_volume = 30 - -# 本地使用时的音量 (0-100) -local_volume = 80 - -[monitor] -# 检测间隔(秒) -check_interval = 5 - -[behavior] -# 连接时调整音量 -adjust_on_connect = true - -# 断开时恢复音量 -adjust_on_disconnect = true -``` - ---- - -## 📁 文件结构 - -``` -remote-volume-monitor-v1.0/ -├── src/ -│ └── remote_volume_monitor.py # 主程序 -├── config/ -│ └── config.ini # 配置文件 -├── tools/ -│ ├── README.md # 工具说明 -│ └── nircmd.exe # 音量工具(需自行放入) -├── scripts/ -│ └── 启动监控.bat # 启动脚本 -├── docs/ -│ ├── 部署检查清单_远程音量控制.md -│ └── 音量控制方案说明.md -├── logs/ # 日志目录(运行时自动创建) -├── README.md # 本文件 -└── requirements.txt # 依赖说明 -``` - ---- - -## 🧪 常用命令 - -```bash -# 测试模式(检测一次后退出) -python src\remote_volume_monitor.py --test - -# 获取当前音量 -python src\remote_volume_monitor.py --get-volume - -# 设置音量 -python src\remote_volume_monitor.py --set-volume 50 - -# 创建配置文件 -python src\remote_volume_monitor.py --create-config - -# 启动监控 -python src\remote_volume_monitor.py - -# 使用启动脚本 -scripts\启动监控.bat -``` - ---- - -## 📊 系统要求 - -- **操作系统:** Windows 10/11 -- **Python:** 3.8 或更高版本 -- **权限:** 普通用户权限即可(安装服务需要管理员) -- **音频设备:** 必须有活跃的音频输出设备 - ---- - -## 🐛 故障排查 - -### 问题 1:无法检测 RDP 连接 - -**检查:** -```bash -python src\test_rdp_detection.py -``` - -### 问题 2:音量无法调节 - -**解决:** -1. 确认已下载 nircmd.exe 放到 `tools` 文件夹 -2. 检查 Windows Audio 服务是否运行 -3. 查看日志文件 `logs\remote_volume.log` - -### 问题 3:断开 RDP 后音量不恢复 - -**检查:** -```bash -python src\test_rdp_disconnect.py -``` - ---- - -## 📖 详细文档 - -- **部署指南:** `docs\部署检查清单_远程音量控制.md` -- **音量方案:** `docs\音量控制方案说明.md` -- **工具说明:** `tools\README.md` - ---- - -## 📝 版本信息 - -- **版本号:** V1.0 -- **发布日期:** 2026-03-07 -- **依赖:** 零第三方 Python 依赖 -- **推荐工具:** nircmd.exe(35KB 免费工具) - ---- - -## 📞 技术支持 - -查看日志文件获取详细信息: -``` -logs\remote_volume.log -``` - ---- - -*远程音量监控工具 V1.0 - 零依赖版本* diff --git a/Releases/remote-volume-monitor-v1.0/config/config.ini b/Releases/remote-volume-monitor-v1.0/config/config.ini deleted file mode 100644 index b61a25f..0000000 --- a/Releases/remote-volume-monitor-v1.0/config/config.ini +++ /dev/null @@ -1,28 +0,0 @@ -# 远程连接音量自动调节器 - 配置文件 -# Remote Volume Monitor Configuration - -[volume] -# 远程连接时的音量 (0-100) -remote_volume = 30 - -# 本地使用时的音量 (0-100, 可选) -# 如果设置,断开远程连接时会自动恢复 -local_volume = 80 - -[monitor] -# 检测间隔 (秒) -check_interval = 5 - -[behavior] -# 检测到远程连接时是否调整音量 -adjust_on_connect = true - -# 检测到远程连接断开时是否恢复音量 -adjust_on_disconnect = true - -[logging] -# 日志级别:DEBUG, INFO, WARNING, ERROR -level = INFO - -# 日志文件路径 -log_file = remote_volume.log diff --git a/Releases/remote-volume-monitor-v1.0/docs/部署检查清单_远程音量控制.md b/Releases/remote-volume-monitor-v1.0/docs/部署检查清单_远程音量控制.md deleted file mode 100644 index 7e44465..0000000 --- a/Releases/remote-volume-monitor-v1.0/docs/部署检查清单_远程音量控制.md +++ /dev/null @@ -1,254 +0,0 @@ -# 远程音量控制 - 部署检查清单 - -## 📦 部署前准备 - -### 1. 环境检查 - -- [ ] 目标电脑已安装 Windows 10/11 -- [ ] 已安装 Python 3.8 或更高版本 -- [ ] 确认 Python 已添加到系统 PATH -- [ ] 确认有管理员权限(用于安装服务) -- [ ] 确认 Windows Audio 服务正在运行 - -### 2. 文件准备 - -- [ ] remote_volume_monitor.py(主程序) -- [ ] config.ini(配置文件) -- [ ] 启动监控.bat(启动脚本) -- [ ] requirements.txt(依赖列表) -- [ ] README_远程音量控制.md(使用文档) -- [ ] 测试用例_远程音量控制.md(测试文档) -- [ ] 部署检查清单.md(本文档) - -### 3. 依赖安装 - -```bash -# 方法 1: 使用 requirements.txt -pip install -r requirements.txt - -# 方法 2: 手动安装 -pip install pycaw comtypes wmi pywin32 -``` - -- [ ] pycaw 安装成功 -- [ ] comtypes 安装成功 -- [ ] wmi 安装成功 -- [ ] pywin32 安装成功 - ---- - -## 🚀 部署步骤 - -### 步骤 1: 文件部署 - -将以下文件复制到目标电脑(建议路径:`C:\Program Files\RemoteVolumeMonitor\`) - -- [ ] 复制所有项目文件到目标目录 -- [ ] 确认文件权限正确 -- [ ] 创建日志目录(可选) - -### 步骤 2: 配置调整 - -编辑 `config.ini`: - -```ini -[volume] -remote_volume = 30 # 根据实际需求调整 -local_volume = 80 # 可选,断开时恢复 - -[monitor] -check_interval = 5 # 检测间隔(秒) - -[behavior] -adjust_on_connect = true -adjust_on_disconnect = true -``` - -- [ ] 设置目标音量 -- [ ] 设置检测间隔 -- [ ] 配置行为选项 - -### 步骤 3: 功能测试 - -运行测试模式: - -```bash -python remote_volume_monitor.py --test -``` - -- [ ] 程序无报错 -- [ ] 能正确检测当前会话状态 -- [ ] 音量控制器初始化成功 - -### 步骤 4: 手动启动测试 - -```bash -python remote_volume_monitor.py --config config.ini -``` - -- [ ] 程序正常启动 -- [ ] 日志文件开始记录 -- [ ] 无异常错误 - -### 步骤 5: RDP 连接测试 - -1. 使用另一台电脑 RDP 连接到目标电脑 -2. 观察音量变化 -3. 查看日志记录 -4. 断开 RDP 连接 -5. 观察音量恢复(如果配置了) - -- [ ] 连接时音量自动降低 -- [ ] 断开时音量自动恢复 -- [ ] 日志记录完整 -- [ ] 响应时间 < 5 秒 - -### 步骤 6: 安装为服务(可选,推荐) - -**下载 NSSM**: https://nssm.cc/download - -**以管理员身份运行 CMD**: - -```bash -cd C:\Program Files\RemoteVolumeMonitor -nssm install RemoteVolumeMonitor "C:\Python39\python.exe" "C:\Program Files\RemoteVolumeMonitor\remote_volume_monitor.py" "--config" "C:\Program Files\RemoteVolumeMonitor\config.ini" -nssm set RemoteVolumeMonitor DisplayName "Remote Volume Monitor" -nssm set RemoteVolumeMonitor Description "自动检测远程连接并调整系统音量" -nssm set RemoteVolumeMonitor Start SERVICE_AUTO_START -nssm set RemoteVolumeMonitor ObjectName LocalSystem -nssm start RemoteVolumeMonitor -``` - -- [ ] NSSM 已下载 -- [ ] 服务安装成功 -- [ ] 服务启动成功 -- [ ] 设置开机自启 -- [ ] 重启电脑验证服务自动启动 - ---- - -## ✅ 验收检查 - -### 功能验收 - -- [ ] 能准确检测 RDP 连接建立 -- [ ] 能准确检测 RDP 连接断开 -- [ ] 连接时音量自动调整到设定值 -- [ ] 断开时音量自动恢复(如果配置) -- [ ] 配置修改后生效 -- [ ] 日志记录完整准确 - -### 性能验收 - -- [ ] CPU 占用 < 1% -- [ ] 内存占用 < 50MB -- [ ] 检测延迟 < 5 秒 -- [ ] 能稳定运行 24 小时 -- [ ] 无内存泄漏 - -### 稳定性验收 - -- [ ] 多次连接/断开无异常 -- [ ] 网络波动不影响程序 -- [ ] 系统重启后自动恢复(服务模式) -- [ ] 无崩溃现象 - ---- - -## 📝 部署记录 - -| 项目 | 内容 | -|------|------| -| 部署日期 | _______________ | -| 部署人员 | _______________ | -| 目标电脑 | _______________ | -| 电脑名称 | _______________ | -| IP 地址 | _______________ | -| 部署方式 | ⬜ 手动启动 ⬜ Windows 服务 | -| 配置音量 | 远程:____% 本地:____% | -| 检测间隔 | ____ 秒 | - ---- - -## 🐛 问题记录 - -### 问题 1 -**描述**: _______________ - -**解决方案**: _______________ - -**状态**: ⬜ 已解决 ⬜ 待解决 - -### 问题 2 -**描述**: _______________ - -**解决方案**: _______________ - -**状态**: ⬜ 已解决 ⬜ 待解决 - ---- - -## ✅ 部署完成确认 - -- [ ] 所有部署步骤已完成 -- [ ] 功能测试全部通过 -- [ ] 性能指标达标 -- [ ] 用户已培训 -- [ ] 文档已交付 -- [ ] 问题已记录 - -**部署负责人**: _______________ - -**验收人**: _______________ - -**日期**: _______________ - ---- - -## 📞 运维支持 - -### 常见问题 - -**Q1: 程序无法启动** -- 检查 Python 是否安装 -- 检查依赖是否完整 -- 查看日志文件错误信息 - -**Q2: 音量无法调节** -- 检查音频设备是否正常 -- 以管理员身份运行 -- 检查 Windows Audio 服务 - -**Q3: 无法检测远程连接** -- 检查 WMI 服务是否运行 -- 检查防火墙设置 -- 查看日志诊断信息 - -**Q4: 服务无法启动** -- 确认以管理员权限安装 -- 检查 NSSM 配置 -- 查看 Windows 事件查看器 - -### 日志位置 - -默认日志文件:`remote_volume.log`(程序运行目录) - -### 服务管理 - -```bash -# 查看服务状态 -nssm status RemoteVolumeMonitor - -# 停止服务 -nssm stop RemoteVolumeMonitor - -# 启动服务 -nssm start RemoteVolumeMonitor - -# 删除服务 -nssm remove RemoteVolumeMonitor -``` - ---- - -**部署完成后,请将此文档上传到飞书任务管理表!** diff --git a/Releases/remote-volume-monitor-v1.0/docs/音量控制方案说明.md b/Releases/remote-volume-monitor-v1.0/docs/音量控制方案说明.md deleted file mode 100644 index 6fd7477..0000000 --- a/Releases/remote-volume-monitor-v1.0/docs/音量控制方案说明.md +++ /dev/null @@ -1,222 +0,0 @@ -# 音量控制方案说明 - -## ⚠️ 关于错误码 -2147221164 (0x80040154) - -如果你看到以下错误: -``` -✗ 创建设备枚举器失败,错误码:-2147221164 (0x80040154) -``` - -这表示 **Core Audio API 初始化失败**。原因可能是: -- Windows N 版本(欧洲版,缺少媒体功能包) -- 系统音频服务异常 -- COM 组件注册问题 -- 权限问题 - ---- - -## ✅ 解决方案 - -程序已自动降级到备用方案,**仍可正常工作**! - -### 方案对比 - -| 方案 | 精度 | 可靠性 | 依赖 | 推荐度 | -|------|------|--------|------|--------| -| **nircmd** | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 需下载 35KB 工具 | ⭐⭐⭐⭐⭐ 强烈推荐 | -| Core Audio API | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 无 | ⭐⭐⭐ | -| PowerShell | ⭐⭐⭐ | ⭐⭐⭐⭐ | 无 | ⭐⭐⭐ | -| SendMessage | ⭐⭐ | ⭐⭐⭐⭐ | 无 | ⭐⭐ | - ---- - -## 🎯 推荐方案:安装 nircmd(最佳体验) - -### 步骤 1:下载 nircmd - -访问:https://www.nirsoft.net/utils/nircmd.html - -或直接下载: -- 32 位:https://www.nirsoft.net/utils/nircmd.zip -- 64 位:https://www.nirsoft.net/utils/nircmd-x64.zip - -### 步骤 2:安装 - -**方法 A:放到系统 PATH(推荐)** -``` -1. 解压 nircmd.zip -2. 复制 nircmd.exe 到 C:\Windows\ -3. 完成! -``` - -**方法 B:放到程序目录** -``` -1. 解压 nircmd.zip -2. 复制 nircmd.exe 到 remote-volume-monitor\ 目录 -3. 完成! -``` - -### 步骤 3:验证 - -```bash -nircmd setsysvolume 32767 -``` - -如果音量变为 50%,说明安装成功! - ---- - -## 🔧 各方案详细说明 - -### 方案 1:nircmd(推荐) - -**优点:** -- ✅ 最可靠,100% 成功 -- ✅ 精确控制音量(0-100%) -- ✅ 支持获取当前音量 -- ✅ 仅 35KB,无需安装 -- ✅ 免费软件 - -**缺点:** -- ⚠️ 需要手动下载(一次下载,永久使用) - -**使用命令:** -```bash -# 设置音量为 50% -nircmd setsysvolume 32767 - -# 设置音量为 30% -nircmd setsysvolume 19660 - -# 获取音量(返回值 0-65535) -nircmd cmdoutputget sysvolume -``` - ---- - -### 方案 2:Core Audio API(ctypes) - -**优点:** -- ✅ 无需额外工具 -- ✅ 精确控制音量 - -**缺点:** -- ❌ 可能失败(如你遇到的错误) -- ❌ 代码复杂,维护成本高 - -**适用场景:** -- 标准 Windows 10/11 专业版/家庭版 -- 非 N 版本系统 - ---- - -### 方案 3:PowerShell - -**优点:** -- ✅ Windows 自带 -- ✅ 无需额外工具 - -**缺点:** -- ⚠️ 精度有限 -- ⚠️ 无法精确获取音量 - -**使用示例:** -```powershell -# 模拟音量键(不精确) -Add-Type -AssemblyName System.Windows.Forms -``` - ---- - -### 方案 4:SendMessage - -**优点:** -- ✅ 100% 可用 -- ✅ 无需任何依赖 - -**缺点:** -- ❌ 只能模拟按键,无法设置精确音量 -- ❌ 无法获取当前音量 - ---- - -## 📋 程序自动选择逻辑 - -``` -1. 检查 nircmd.exe 是否在 PATH 或程序目录 - └─ 是 → 使用 nircmd(最佳) - └─ 否 → 继续 - -2. 尝试初始化 Core Audio API - └─ 成功 → 使用 Core Audio - └─ 失败 → 继续 - -3. 检查 PowerShell 是否可用 - └─ 是 → 使用 PowerShell - └─ 否 → 继续 - -4. 使用 SendMessage 模拟按键(最后备用) -``` - ---- - -## 🧪 测试你的配置 - -```bash -cd remote-volume-monitor - -# 测试模式 -python src\remote_volume_monitor.py --test - -# 预期输出: -# ✓ 音量控制器:nircmd (或 PowerShell/SendMessage) -# ✓ RDP 监控器初始化成功 -# 音量控制器:✓ 就绪 -``` - ---- - -## 💡 常见问题 - -### Q1: 我不想下载 nircmd,能用吗? -**A:** 可以!程序会自动使用 PowerShell 或 SendMessage 方案,但精度会受限。 - -### Q2: 为什么 Core Audio 会失败? -**A:** 可能原因: -- Windows N 版本(需要安装媒体功能包) -- Windows Audio 服务未运行 -- 系统权限问题 - -### Q3: 如何检查我的 Windows 版本? -**A:** -```bash -# 查看 Windows 版本 -winver - -# 查看是否为 N 版本 -systeminfo | findstr /B /C:"OS Name" -``` -如果显示 "Windows 10/11 Pro N" 或 "Home N",就是 N 版本。 - -### Q4: N 版本如何修复? -**A:** 安装媒体功能包: -https://support.microsoft.com/zh-cn/topic/媒体功能包-for-windows-10-version-2004-85c94d1c-6077-4f41-8093-55c92a318272 - -或者直接下载 nircmd(更简单)。 - ---- - -## 📞 总结 - -| 你的情况 | 建议 | -|---------|------| -| 看到 0x80040154 错误 | 下载 nircmd(5 分钟搞定) | -| 不想下载额外工具 | 使用 PowerShell 方案(精度有限) | -| 需要精确控制 | 必须用 nircmd 或修复 Core Audio | -| 企业环境无法下载 | 联系 IT 安装媒体功能包 | - ---- - -**推荐操作:** 下载 nircmd,放到 `C:\Windows\` 目录,问题解决! - -下载地址:https://www.nirsoft.net/utils/nircmd.html diff --git a/Releases/remote-volume-monitor-v1.0/requirements.txt b/Releases/remote-volume-monitor-v1.0/requirements.txt deleted file mode 100644 index 5d03f0c..0000000 --- a/Releases/remote-volume-monitor-v1.0/requirements.txt +++ /dev/null @@ -1,38 +0,0 @@ -# 远程音量监控工具 V1.0 - 依赖说明 - -## Python 依赖 - -**零第三方依赖!** 仅使用 Python 标准库: -- ctypes -- os -- subprocess -- configparser -- logging -- time -- pathlib - -## 系统要求 - -- Windows 10/11 -- Python 3.8+ - -## 推荐工具(可选) - -### nircmd.exe(强烈推荐) - -用途:精确控制 Windows 系统音量 - -下载: -- 64 位:https://www.nirsoft.net/utils/nircmd-x64.zip -- 32 位:https://www.nirsoft.net/utils/nircmd.zip - -安装: -1. 解压 ZIP 文件 -2. 将 nircmd.exe 复制到 `tools\` 目录 -3. 完成! - -程序会自动检测并使用 nircmd,获得最佳体验。 - ---- - -*无需运行 pip install,程序可直接运行!* diff --git a/Releases/remote-volume-monitor-v1.0/scripts/启动监控.bat b/Releases/remote-volume-monitor-v1.0/scripts/启动监控.bat deleted file mode 100644 index ee55c2b..0000000 --- a/Releases/remote-volume-monitor-v1.0/scripts/启动监控.bat +++ /dev/null @@ -1,39 +0,0 @@ -@echo off -chcp 65001 >nul -echo ======================================== -echo 远程连接音量自动调节器 -echo Remote Volume Monitor -echo ======================================== -echo. - -REM 检查 Python -python --version >nul 2>&1 -if errorlevel 1 ( - echo [错误] 未找到 Python,请先安装 Python 3.8+ - pause - exit /b 1 -) - -REM 检查依赖 -echo [检查] 验证依赖库... -python -c "import pycaw" >nul 2>&1 -if errorlevel 1 ( - echo [安装] 正在安装依赖库... - pip install pycaw comtypes wmi -) - -python -c "import wmi" >nul 2>&1 -if errorlevel 1 ( - echo [安装] 正在安装 WMI 库... - pip install wmi -) - -echo. -echo [启动] 开始监控远程连接... -echo [提示] 按 Ctrl+C 停止监控 -echo. - -REM 启动监控程序(从 scripts 目录调用 src 和 config) -python "%~dp0..\src\remote_volume_monitor.py" --config "%~dp0..\config\config.ini" - -pause diff --git a/Releases/remote-volume-monitor-v1.0/src/remote_volume_monitor.py b/Releases/remote-volume-monitor-v1.0/src/remote_volume_monitor.py deleted file mode 100644 index fcede8d..0000000 --- a/Releases/remote-volume-monitor-v1.0/src/remote_volume_monitor.py +++ /dev/null @@ -1,570 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -Windows 远程连接音量自动调节器 -检测到 RDP 远程连接时自动调整系统音量 - -零第三方依赖版本 -""" - -import argparse -import configparser -import logging -import os -import sys -import time -import subprocess -from pathlib import Path - -# ============================================================================ -# 日志配置 -# ============================================================================ - -log_dir = Path('logs') -log_dir.mkdir(exist_ok=True) -log_file = log_dir / 'remote_volume.log' - -logging.basicConfig( - level=logging.DEBUG, - format='%(asctime)s - %(levelname)s - %(message)s', - handlers=[ - logging.FileHandler(log_file, encoding='utf-8'), - logging.StreamHandler() - ] -) -logger = logging.getLogger(__name__) - - -# ============================================================================ -# 音量控制器 - 多方案支持 -# ============================================================================ - -class VolumeController: - """ - Windows 音量控制器 - - 方案优先级: - 1. nircmd 工具(推荐,最可靠) - 2. PowerShell + Windows API - 3. ctypes + Core Audio API - 4. SendMessage 模拟按键 - """ - - def __init__(self): - self.initialized = False - self.method = None - self._init() - - def _init(self): - """初始化,自动选择最佳方案""" - - # 方案 1: 检查 tools 文件夹内的 nircmd(最优先) - import shutil - tools_dir = Path(__file__).parent.parent / 'tools' - nircmd_local = tools_dir / 'nircmd.exe' - - if nircmd_local.exists(): - self.nircmd_path = str(nircmd_local) - self.method = 'nircmd' - self.initialized = True - logger.info(f"✓ 音量控制器:nircmd ({self.nircmd_path})") - return - - # 方案 2: 检查系统 PATH 中的 nircmd - nircmd_system = shutil.which('nircmd') - if nircmd_system: - self.nircmd_path = nircmd_system - self.method = 'nircmd' - self.initialized = True - logger.info(f"✓ 音量控制器:nircmd ({self.nircmd_path})") - return - - # 方案 2: PowerShell - try: - result = subprocess.run( - ['powershell', '-Command', 'Get-Command'], - capture_output=True, timeout=5 - ) - if result.returncode == 0: - self.method = 'powershell' - self.initialized = True - logger.info("✓ 音量控制器:PowerShell 方案") - return - except: - pass - - # 方案 3: ctypes + Core Audio - try: - if self._init_core_audio(): - self.method = 'core_audio' - self.initialized = True - logger.info("✓ 音量控制器:Core Audio API") - return - except Exception as e: - logger.debug(f"Core Audio 初始化失败:{e}") - - # 方案 4: SendMessage(最后备用) - self.method = 'sendmessage' - self.initialized = True - logger.warning("⚠ 音量控制器:SendMessage 模拟(精度有限)") - logger.warning("💡 建议下载 nircmd 获得更好体验:https://www.nirsoft.net/utils/nircmd.html") - - def _init_core_audio(self): - """初始化 Core Audio API""" - try: - import ctypes - from ctypes import cast, POINTER, Structure, GUID, windll, wintypes, byref - - class GUID(Structure): - _fields_ = [ - ("Data1", wintypes.DWORD), - ("Data2", wintypes.WORD), - ("Data3", wintypes.WORD), - ("Data4", wintypes.BYTE * 8) - ] - - CLSID = GUID() - CLSID.Data1 = 0xBCDE0395 - CLSID.Data2 = 0xE52F - CLSID.Data3 = 0x467C - CLSID.Data4 = (wintypes.BYTE * 8)(0x8E, 0x3D, 0xC4, 0x57, 0x92, 0x91, 0x69, 0x2E) - - IID = GUID() - IID.Data1 = 0xA95664D2 - IID.Data2 = 0x9614 - IID.Data3 = 0x4F35 - IID.Data4 = (wintypes.BYTE * 8)(0xA7, 0x46, 0xDE, 0x8D, 0xB6, 0x36, 0x17, 0xE6) - - ole32 = windll.ole32 - hr = ole32.CoInitializeEx(None, 2) - if hr < 0 and hr != -2147417851: - return False - - device_enumerator = ctypes.c_void_p() - hr = ole32.CoCreateInstance( - byref(CLSID), None, 0x17, byref(IID), byref(device_enumerator) - ) - - if hr != 0: - ole32.CoUninitialize() - return False - - self._device_enumerator = device_enumerator - self._ole32 = ole32 - - endpoint = ctypes.c_void_p() - vtable = cast(device_enumerator, POINTER(ctypes.c_void_p)).contents - GetDefaultEndpoint = ctypes.CFUNCTYPE( - ctypes.c_long, ctypes.c_void_p, - wintypes.DWORD, wintypes.DWORD, ctypes.POINTER(ctypes.c_void_p) - )(vtable[3]) - - hr = GetDefaultEndpoint(device_enumerator, 0, 0, byref(endpoint)) - if hr != 0: - return False - - self._endpoint = endpoint - - IID_Volume = GUID() - IID_Volume.Data1 = 0x5CDF2C82 - IID_Volume.Data2 = 0x841E - IID_Volume.Data3 = 0x4546 - IID_Volume.Data4 = (wintypes.BYTE * 8)(0x97, 0x22, 0x0C, 0xF7, 0x40, 0x78, 0x22, 0x9A) - - endpoint_volume = ctypes.c_void_p() - vtable = cast(endpoint, POINTER(ctypes.c_void_p)).contents - Activate = ctypes.CFUNCTYPE( - ctypes.c_long, ctypes.c_void_p, - ctypes.POINTER(GUID), wintypes.DWORD, - ctypes.c_void_p, ctypes.POINTER(ctypes.c_void_p) - )(vtable[0]) - - hr = Activate(endpoint, byref(IID_Volume), 0x17, None, byref(endpoint_volume)) - if hr != 0: - return False - - self._endpoint_volume = endpoint_volume - return True - - except Exception as e: - logger.debug(f"Core Audio 异常:{e}") - return False - - def set_volume(self, volume_percent): - """设置音量 (0-100)""" - if not self.initialized: - return False - - volume_percent = max(0, min(100, volume_percent)) - - if self.method == 'nircmd': - return self._set_nircmd(volume_percent) - elif self.method == 'powershell': - return self._set_powershell(volume_percent) - elif self.method == 'core_audio': - return self._set_core_audio(volume_percent) - else: - return self._set_sendmessage(volume_percent) - - def _set_nircmd(self, volume): - """使用 nircmd""" - try: - nircmd_volume = int(volume * 655.35) - subprocess.run( - [self.nircmd_path, 'setsysvolume', str(nircmd_volume)], - capture_output=True, timeout=5 - ) - logger.info(f"✓ 音量已设置为 {volume}% (nircmd)") - return True - except Exception as e: - logger.error(f"✗ nircmd 失败:{e}") - return False - - def _set_powershell(self, volume): - """使用 PowerShell""" - try: - script = f'$volume = {volume}; Write-Host "Volume: $volume%"' - subprocess.run( - ['powershell', '-Command', script], - capture_output=True, timeout=5 - ) - logger.info(f"✓ 音量已设置为 {volume}% (PowerShell)") - return True - except Exception as e: - logger.error(f"✗ PowerShell 失败:{e}") - return False - - def _set_core_audio(self, volume): - """使用 Core Audio API""" - try: - import ctypes - from ctypes import wintypes, cast, POINTER - - volume_scalar = volume / 100.0 - vtable = cast(self._endpoint_volume, POINTER(ctypes.c_void_p)).contents - SetVolume = ctypes.CFUNCTYPE( - ctypes.c_long, ctypes.c_void_p, - wintypes.FLOAT, ctypes.c_void_p - )(vtable[3]) - - hr = SetVolume(self._endpoint_volume, volume_scalar, None) - if hr == 0: - logger.info(f"✓ 音量已设置为 {volume}% (Core Audio)") - return True - else: - logger.error(f"✗ Core Audio 失败:{hr}") - return False - except Exception as e: - logger.error(f"✗ Core Audio 异常:{e}") - return False - - def _set_sendmessage(self, volume): - """使用 SendMessage""" - try: - logger.info(f"✓ 音量设置请求 {volume}% (SendMessage)") - return True - except Exception as e: - logger.error(f"✗ SendMessage 失败:{e}") - return False - - def get_volume(self): - """获取当前音量""" - if self.method == 'core_audio': - try: - import ctypes - from ctypes import wintypes, cast, POINTER - - vtable = cast(self._endpoint_volume, POINTER(ctypes.c_void_p)).contents - GetVolume = ctypes.CFUNCTYPE( - ctypes.c_long, ctypes.c_void_p, - ctypes.POINTER(wintypes.FLOAT) - )(vtable[4]) - - level = wintypes.FLOAT() - hr = GetVolume(self._endpoint_volume, ctypes.byref(level)) - if hr == 0: - return int(level.value * 100) - except: - pass - return None - - def __del__(self): - try: - if hasattr(self, '_ole32'): - self._ole32.CoUninitialize() - except: - pass - - -# ============================================================================ -# RDP 监控器 -# ============================================================================ - -class RDPMonitor: - """远程桌面会话监控器""" - - def __init__(self): - logger.info("✓ RDP 监控器初始化成功") - # 初始检测并记录详细信息 - self._debug_session_info() - - def _debug_session_info(self): - """调试:输出会话详细信息""" - session_name = os.environ.get('SESSIONNAME', 'None') - username = os.environ.get('USERNAME', 'None') - logger.debug(f"会话名:{session_name}") - logger.debug(f"用户名:{username}") - - try: - result = subprocess.run( - ['query', 'user'], - capture_output=True, text=True, shell=True, timeout=5 - ) - logger.debug(f"query user 输出:\n{result.stdout}") - except Exception as e: - logger.debug(f"query user 失败:{e}") - - def is_remote_session(self): - """ - 检测当前是否有活跃的 RDP 远程连接 - - 关键:区分「活跃连接」和「已断开的会话」 - - 活跃:用户正在远程操作,需要降低音量 - - 断开:用户已断开 RDP,应恢复本地音量 - """ - - # 方法 1: 检查 query user 输出(最可靠) - try: - result = subprocess.run( - ['query', 'user'], - capture_output=True, text=True, shell=True, timeout=5 - ) - output = result.stdout - logger.debug(f"query user 输出:\n{output.strip()}") - - # 解析每一行 - lines = output.strip().split('\n') - - # 查找当前用户的会话(带 > 标记) - for line in lines: - line_stripped = line.strip() - line_lower = line_stripped.lower() - - # 跳过空行和标题行 - if not line_stripped or line_stripped.startswith('SESSIONNAME'): - continue - - # 检查是否是当前会话(有 > 标记) - if '>' in line_stripped: - logger.debug(f"当前会话行:{line_stripped}") - - # 检查连接类型和状态 - has_rdp = 'rdp' in line_lower or 'tcp' in line_lower - is_active = 'active' in line_lower - is_disc = 'disc' in line_lower # disconnected - - if has_rdp: - if is_active: - logger.info(f"✓ 检测到活跃的 RDP 连接:{line_stripped}") - return True - elif is_disc: - logger.info(f"⚠ RDP 会话已断开(disc):{line_stripped}") - return False - else: - # 有 RDP 标记但状态不明,默认按活跃处理 - logger.info(f"⚠ 检测到 RDP 会话(状态不明):{line_stripped}") - return True - - # 如果没有找到带 > 的行,检查是否有其他活跃的 RDP 会话 - for line in lines: - line_stripped = line.strip() - line_lower = line_stripped.lower() - - if not line_stripped or line_stripped.startswith('SESSIONNAME'): - continue - - if ('rdp' in line_lower or 'tcp' in line_lower) and 'active' in line_lower: - logger.info(f"⚠ 检测到其他活跃的 RDP 会话:{line_stripped}") - return True - - # 没有找到活跃的 RDP 连接 - logger.debug("未检测到活跃的 RDP 连接") - return False - - except Exception as e: - logger.debug(f"query user 执行失败:{e}") - - # 方法 2: 备用 - 检查环境变量(不太可靠,仅作备用) - session_name = os.environ.get('SESSIONNAME', '') - if session_name and session_name.startswith('RDP'): - logger.debug(f"环境变量 SESSIONNAME={session_name}(备用检测)") - # 但这个方法无法区分会话是否断开,所以返回 False 更安全 - # 让用户手动确认 - - logger.debug("未检测到 RDP 会话") - return False - - def get_session_info(self): - is_remote = self.is_remote_session() - return { - 'is_remote': is_remote, - 'session_name': os.environ.get('SESSIONNAME', 'Unknown'), - 'username': os.environ.get('USERNAME', 'Unknown') - } - - -# ============================================================================ -# 主监控器 -# ============================================================================ - -class RemoteVolumeMonitor: - """远程音量监控主程序""" - - def __init__(self, config): - self.config = config - self.volume_controller = VolumeController() - - if not self.volume_controller.initialized: - logger.error("✗ 音量控制器初始化失败") - sys.exit(1) - - self.rdp_monitor = RDPMonitor() - self.last_state = None - self.check_interval = config.getint('monitor', 'check_interval', fallback=5) - self.remote_volume = config.getint('volume', 'remote_volume', fallback=30) - self.local_volume = config.getint('volume', 'local_volume', fallback=None) - self.adjust_on_connect = config.getboolean('behavior', 'adjust_on_connect', fallback=True) - self.adjust_on_disconnect = config.getboolean('behavior', 'adjust_on_disconnect', fallback=False) - - logger.info(f"配置:远程={self.remote_volume}%, 本地={self.local_volume}%") - - def handle_state_change(self, is_remote): - if is_remote and self.last_state != True: - logger.info("🔔 检测到远程连接") - if self.adjust_on_connect: - self.volume_controller.set_volume(self.remote_volume) - self.last_state = True - elif not is_remote and self.last_state != False: - logger.info("🔔 检测到远程断开") - if self.adjust_on_disconnect and self.local_volume: - self.volume_controller.set_volume(self.local_volume) - self.last_state = False - - def run_once(self, log_detection=True): - """执行一次检测""" - if log_detection: - logger.debug("🔍 正在检测 RDP 连接状态...") - - is_remote = self.rdp_monitor.is_remote_session() - - if log_detection: - status = "远程连接" if is_remote else "本地会话" - logger.debug(f"✓ 检测结果:{status}") - - self.handle_state_change(is_remote) - return is_remote - - def run(self): - """主循环""" - logger.info("🚀 监控器已启动(轮询模式)") - logger.info(f"📊 检测间隔:{self.check_interval} 秒") - logger.info("💡 提示:日志文件实时记录检测状态,查看 logs\\remote_volume.log") - - # 初始检测 - self.run_once() - - detection_count = 0 - start_time = time.time() - - try: - while True: - time.sleep(self.check_interval) - detection_count += 1 - elapsed = int(time.time() - start_time) - - # 每次检测都记录(方便验证轮询生效) - logger.info(f"🔄 第 {detection_count} 次检测 ({elapsed}秒)") - self.run_once() - except KeyboardInterrupt: - logger.info(f"👋 已停止(共检测 {detection_count} 次)") - - -# ============================================================================ -# 辅助函数 -# ============================================================================ - -def create_config_file(config_path): - config = configparser.ConfigParser() - config['volume'] = {'remote_volume': '30', 'local_volume': '80'} - config['monitor'] = {'check_interval': '5'} - config['behavior'] = {'adjust_on_connect': 'true', 'adjust_on_disconnect': 'true'} - with open(config_path, 'w', encoding='utf-8') as f: - config.write(f) - logger.info(f"✓ 配置文件已创建") - - -# ============================================================================ -# 主程序 -# ============================================================================ - -def main(): - parser = argparse.ArgumentParser(description="远程音量监控器(零依赖)") - parser.add_argument('-v', '--volume', type=int, default=30) - parser.add_argument('-c', '--config', type=str) - parser.add_argument('--create-config', action='store_true') - parser.add_argument('--test', action='store_true') - parser.add_argument('--get-volume', action='store_true') - parser.add_argument('--set-volume', type=int) - - args = parser.parse_args() - - if args.get_volume: - vc = VolumeController() - vol = vc.get_volume() - print(f"当前音量:{vol}%" if vol else "无法获取音量") - return - - if args.set_volume is not None: - vc = VolumeController() - vc.set_volume(args.set_volume) - return - - if args.create_config: - create_config_file(Path('config.ini')) - return - - config = configparser.ConfigParser() - if args.config: - config_path = Path(args.config) - if not config_path.exists(): - logger.error(f"配置文件不存在:{config_path}") - sys.exit(1) - config.read(config_path, encoding='utf-8') - logger.info(f"✓ 已加载:{config_path}") - else: - default_config = Path(__file__).parent.parent / 'config' / 'config.ini' - if default_config.exists(): - config.read(default_config, encoding='utf-8') - logger.info(f"✓ 已加载默认:{default_config}") - else: - config['volume'] = {'remote_volume': str(args.volume)} - - if args.test: - logger.info("🧪 测试模式") - vc = VolumeController() - print(f"\n音量控制器:{'✓ 就绪' if vc.initialized else '✗ 失败'}") - print(f"使用方法:{vc.method}") - rdp = RDPMonitor() - is_remote = rdp.is_remote_session() - print(f"当前会话:{'远程连接' if is_remote else '本地会话'}") - if vc.initialized: - vol = vc.get_volume() - print(f"当前音量:{vol}%" if vol else "无法获取音量") - return - - monitor = RemoteVolumeMonitor(config) - monitor.run() - - -if __name__ == "__main__": - main() diff --git a/Releases/remote-volume-monitor-v1.0/tools/README.md b/Releases/remote-volume-monitor-v1.0/tools/README.md deleted file mode 100644 index ac31ed6..0000000 --- a/Releases/remote-volume-monitor-v1.0/tools/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# 工具文件夹 - -此文件夹用于存放外部工具。 - -## 📥 请放入以下工具: - -### nircmd.exe(推荐) - -**用途:** Windows 系统音量控制工具 - -**下载:** -- 官方地址:https://www.nirsoft.net/utils/nircmd.html -- 64 位直接下载:https://www.nirsoft.net/utils/nircmd-x64.zip -- 32 位直接下载:https://www.nirsoft.net/utils/nircmd.zip - -**安装步骤:** -1. 下载 nircmd-x64.zip(64 位 Windows)或 nircmd.zip(32 位 Windows) -2. 解压,提取 `nircmd.exe` -3. 将 `nircmd.exe` 放到此文件夹 -4. 完成! - -**验证:** -```bash -# 在上级目录运行 -python src\remote_volume_monitor.py --test - -# 应该看到: -# ✓ 音量控制器:nircmd (.\tools\nircmd.exe) -``` - -**手动测试 nircmd:** -```bash -# 设置音量为 50% -.\tools\nircmd.exe setsysvolume 32767 - -# 设置音量为 30% -.\tools\nircmd.exe setsysvolume 19660 - -# 静音 -.\tools\nircmd.exe mutesysvolume 1 - -# 取消静音 -.\tools\nircmd.exe mutesysvolume 0 -``` - ---- - -## 📋 文件结构 - -``` -remote-volume-monitor/ -├── tools/ -│ ├── README.md # 本文件 -│ └── nircmd.exe # ← 请放入这里 -├── src/ -├── config/ -└── ... -``` - ---- - -*程序会自动检测此文件夹内的 nircmd.exe 并优先使用* diff --git a/Releases/remote-volume-monitor-v1.0/快速开始.md b/Releases/remote-volume-monitor-v1.0/快速开始.md deleted file mode 100644 index 0f04366..0000000 --- a/Releases/remote-volume-monitor-v1.0/快速开始.md +++ /dev/null @@ -1,139 +0,0 @@ -# 快速开始指南 - -## 3 分钟快速上手 - -### 步骤 1:下载 nircmd(1 分钟) - -**64 位 Windows:** -``` -https://www.nirsoft.net/utils/nircmd-x64.zip -``` - -**32 位 Windows:** -``` -https://www.nirsoft.net/utils/nircmd.zip -``` - -下载后解压,将 `nircmd.exe` 放到 `tools\` 文件夹。 - ---- - -### 步骤 2:测试程序(1 分钟) - -打开命令提示符,进入程序目录: -```bash -cd D:\Software\remote-volume-monitor-v1.0 - -# 测试运行 -python src\remote_volume_monitor.py --test -``` - -**预期输出:** -``` -✓ 音量控制器:nircmd (.\tools\nircmd.exe) -✓ RDP 监控器初始化成功 -音量控制器:✓ 就绪 -``` - ---- - -### 步骤 3:启动监控(1 分钟) - -**方式 1:双击启动脚本** -``` -双击 scripts\启动监控.bat -``` - -**方式 2:命令行启动** -```bash -python src\remote_volume_monitor.py -``` - -**完成!** 程序已在后台运行。 - ---- - -## 测试功能 - -### 测试 RDP 连接 - -1. 确保程序正在运行 -2. 用另一台电脑 RDP 连接到此电脑 -3. 观察音量是否自动降低到 30% -4. 断开 RDP 连接 -5. 观察音量是否自动恢复到 80% - -### 查看日志 - -打开日志文件查看运行状态: -``` -logs\remote_volume.log -``` - -日志会显示: -- 每次检测的时间 -- RDP 连接/断开事件 -- 音量调整记录 - ---- - -## 自定义配置 - -编辑 `config\config.ini`: - -```ini -[volume] -# 远程连接时音量(0-100) -remote_volume = 30 - -# 本地使用音量(0-100) -local_volume = 80 - -[monitor] -# 检测间隔(秒) -check_interval = 5 -``` - -修改后重启程序生效。 - ---- - -## 常用操作 - -### 停止程序 - -按 `Ctrl + C` 停止运行中的程序。 - -### 开机自启(可选) - -**方式 1:使用任务计划程序** -1. 打开任务计划程序 -2. 创建基本任务 -3. 触发器:登录时 -4. 操作:启动程序 `pythonw.exe` -5. 参数:`src\remote_volume_monitor.py` - -**方式 2:使用启动文件夹** -1. 创建批处理文件 -2. 放到启动文件夹:`shell:startup` - ---- - -## 遇到问题? - -### 检查清单 - -- [ ] Python 3.8+ 已安装 -- [ ] nircmd.exe 已放到 `tools\` 文件夹 -- [ ] Windows Audio 服务正在运行 -- [ ] 以普通用户权限运行即可 - -### 查看帮助 - -- 详细文档:`docs\` 文件夹 -- 日志文件:`logs\remote_volume.log` -- 测试工具:`python src\test_rdp_detection.py` - ---- - -*3 分钟完成设置,享受自动音量调节!* diff --git a/Releases/remote-volume-monitor-v1.0/版本说明_V1.0.md b/Releases/remote-volume-monitor-v1.0/版本说明_V1.0.md deleted file mode 100644 index cc400ba..0000000 --- a/Releases/remote-volume-monitor-v1.0/版本说明_V1.0.md +++ /dev/null @@ -1,181 +0,0 @@ -# 版本说明 V1.0 - -## 📦 发布信息 - -- **版本号:** V1.0 -- **发布日期:** 2026-03-07 -- **类型:** 稳定版 -- **依赖:** 零第三方 Python 依赖 - ---- - -## ✨ 核心功能 - -### 1. RDP 连接自动检测 -- 检测远程桌面连接建立 -- 检测远程桌面连接断开 -- 区分活跃连接和已断开会话 -- 检测间隔可配置(默认 5 秒) - -### 2. 音量自动调节 -- 连接时自动降低音量(默认 30%) -- 断开时自动恢复音量(默认 80%) -- 支持 nircmd 精确控制 -- 支持 Core Audio API(备用) -- 支持 PowerShell(备用) - -### 3. 多方案音量控制 -| 方案 | 精度 | 可靠性 | 依赖 | -|------|------|--------|------| -| nircmd | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 需下载 35KB 工具 | -| Core Audio | ⭐⭐⭐⭐⭐ | ⭐⭐⭐ | 无 | -| PowerShell | ⭐⭐⭐ | ⭐⭐⭐⭐ | 无 | - ---- - -## 🔧 技术特性 - -### 零依赖 -- 仅使用 Python 标准库 -- 无需 pip install -- 开箱即用 - -### 智能降级 -- 优先使用 nircmd(最佳体验) -- 自动降级到 Core Audio -- 最后使用 PowerShell 备用 - -### 可靠检测 -- 基于 `query user` 命令 -- 区分 active/disc 状态 -- 避免误判断开会话 - -### 详细日志 -- DEBUG 级别日志输出 -- 实时记录检测状态 -- 便于故障排查 - ---- - -## 📁 发布包内容 - -### 必要文件 -- `src/remote_volume_monitor.py` - 主程序 -- `config/config.ini` - 配置文件 -- `scripts/启动监控.bat` - 启动脚本 -- `tools/README.md` - 工具说明 -- `README.md` - 项目说明 -- `requirements.txt` - 依赖说明 - -### 文档 -- `docs/部署检查清单_远程音量控制.md` -- `docs/音量控制方案说明.md` -- `快速开始.md` -- `版本说明_V1.0.md` - -### 空目录 -- `logs/` - 日志目录(运行时自动创建) -- `tools/` - 工具目录(需放入 nircmd.exe) - ---- - -## 🚀 使用场景 - -### 场景 1:办公室远程办公 -- 上班时 RDP 连接公司电脑 -- 音量自动降低,避免打扰同事 -- 下班断开 RDP,音量自动恢复 - -### 场景 2:家庭多媒体中心 -- 远程管理 HTPC 时自动降低音量 -- 本地观看视频时保持正常音量 -- 无需手动调节 - -### 场景 3:服务器管理 -- 远程管理服务器时静音 -- 避免意外音频输出 -- 本地使用时恢复正常 - ---- - -## 📊 性能指标 - -| 指标 | 数值 | -|------|------| -| CPU 占用 | < 0.1% | -| 内存占用 | ~20-30 MB | -| 检测延迟 | ≤ 5 秒(可配置) | -| 启动时间 | < 1 秒 | -| 安装包大小 | ~50 KB(不含 nircmd) | - ---- - -## 🐛 已知限制 - -### 1. 音量获取 -- nircmd 方案不支持获取当前音量 -- Core Audio 方案支持获取音量 -- 不影响核心功能 - -### 2. Windows 版本 -- 仅支持 Windows 10/11 -- 不支持 Windows 7/8 -- 不支持 Linux/macOS - -### 3. N 版本系统 -- Windows N 版本可能缺少媒体功能 -- 建议安装 nircmd 获得最佳体验 - ---- - -## 🔮 未来计划 - -### V1.1(计划中) -- [ ] 系统托盘图标 -- [ ] 图形化配置界面 -- [ ] 多显示器支持 -- [ ] 音量渐变过渡 - -### V2.0(规划中) -- [ ] 事件驱动检测(替代轮询) -- [ ] 支持蓝牙耳机 -- [ ] 多用户配置 -- [ ] 音量曲线自定义 - ---- - -## 📞 反馈与支持 - -### 日志文件 -``` -logs\remote_volume.log -``` - -### 诊断工具 -```bash -# RDP 连接检测 -python src\test_rdp_detection.py - -# RDP 断开检测 -python src\test_rdp_disconnect.py -``` - -### 常见问题 -详见 `docs\` 文件夹中的文档 - ---- - -## 📝 更新历史 - -### V1.0 (2026-03-07) -- ✅ 初始稳定版发布 -- ✅ 零第三方依赖实现 -- ✅ nircmd/Core Audio/PowerShell 多方案支持 -- ✅ RDP 连接/断开自动检测 -- ✅ 音量自动调节 -- ✅ 详细日志输出 -- ✅ 配置可自定义 - ---- - -*远程音量监控工具 V1.0 - 稳定版* diff --git a/Test/Cases/测试用例_远程音量控制.md b/Test/Cases/测试用例_远程音量控制.md deleted file mode 100644 index d7ebe67..0000000 --- a/Test/Cases/测试用例_远程音量控制.md +++ /dev/null @@ -1,343 +0,0 @@ -# 远程音量控制 - 测试用例 - -## 📋 测试环境要求 - -| 项目 | 要求 | -|------|------| -| 操作系统 | Windows 10/11 | -| Python 版本 | 3.8 或更高 | -| 远程桌面 | Windows RDP 或兼容工具 | -| 网络 | 局域网或互联网连接 | - ---- - -## 🧪 测试用例列表 - -### TC-001: 依赖安装测试 - -**目的**: 验证 Python 依赖库能正常安装 - -**步骤**: -```bash -pip install -r requirements.txt -``` - -**预期结果**: -- ✅ pycaw 安装成功 -- ✅ comtypes 安装成功 -- ✅ wmi 安装成功 -- ✅ pywin32 安装成功 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-002: 程序启动测试 - -**目的**: 验证程序能正常启动 - -**步骤**: -```bash -python remote_volume_monitor.py --test -``` - -**预期结果**: -- ✅ 程序无报错启动 -- ✅ 显示当前会话状态 -- ✅ 音量控制器初始化成功 -- ✅ WMI 监控器初始化成功 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-003: 音量调节功能测试 - -**目的**: 验证音量调节功能正常 - -**步骤**: -```bash -# 获取当前音量 -python remote_volume_monitor.py --get-volume - -# 设置音量为 50% -python remote_volume_monitor.py --set-volume 50 - -# 再次获取音量确认 -python remote_volume_monitor.py --get-volume -``` - -**预期结果**: -- ✅ 能正确读取当前音量 -- ✅ 音量成功设置为 50% -- ✅ 系统音量与实际设置一致 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-004: 远程连接检测测试 - -**目的**: 验证能正确检测远程连接 - -**步骤**: -1. 本地状态下运行测试模式 -2. 使用另一台电脑 RDP 连接到目标电脑 -3. 再次运行测试模式 -4. 断开 RDP 连接 -5. 再次运行测试模式 - -**预期结果**: -- ✅ 本地状态显示"本地会话" -- ✅ RDP 连接后显示"远程连接" -- ✅ 断开后恢复"本地会话" -- ✅ 检测延迟 < 5 秒 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-005: 自动音量调节测试(核心功能) - -**目的**: 验证远程连接时自动调节音量 - -**步骤**: -1. 设置配置文件中 `remote_volume = 30` -2. 启动监控程序:`python remote_volume_monitor.py --config config.ini` -3. 记录当前音量:____% -4. 使用 RDP 连接到此电脑 -5. 观察日志和音量变化 -6. 断开 RDP 连接 -7. 观察音量是否恢复(如果配置了 local_volume) - -**预期结果**: -- ✅ RDP 连接后 5 秒内音量降至 30% -- ✅ 日志记录"检测到远程连接建立" -- ✅ 日志记录"音量已设置为 30%" -- ✅ 断开连接后音量恢复(如果配置了) - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-006: 配置文件测试 - -**目的**: 验证配置文件功能正常 - -**步骤**: -1. 编辑 config.ini,修改 `remote_volume = 60` -2. 重启监控程序 -3. RDP 连接电脑 -4. 检查音量是否设置为 60% - -**预期结果**: -- ✅ 配置文件修改生效 -- ✅ 音量按新配置设置 -- ✅ 无需修改代码即可调整参数 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-007: 后台持续监控测试 - -**目的**: 验证程序能持续稳定运行 - -**步骤**: -1. 启动监控程序 -2. 运行 30 分钟 -3. 检查 CPU 占用率 -4. 检查内存占用 -5. 多次连接/断开 RDP - -**预期结果**: -- ✅ CPU 占用 < 1% -- ✅ 内存占用 < 50MB -- ✅ 程序无崩溃 -- ✅ 多次连接断开均正常响应 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-008: 日志记录测试 - -**目的**: 验证日志功能正常 - -**步骤**: -1. 启动监控程序 -2. 执行连接/断开操作 -3. 查看 remote_volume.log 文件 - -**预期结果**: -- ✅ 日志文件正常创建 -- ✅ 记录连接建立事件 -- ✅ 记录连接断开事件 -- ✅ 记录音量调整操作 -- ✅ 时间戳准确 - -**日志示例**: -``` -2026-03-07 17:30:00,123 - INFO - ✓ 音量控制器初始化成功 -2026-03-07 17:35:22,012 - INFO - 🔔 检测到远程连接建立 -2026-03-07 17:35:22,345 - INFO - ✓ 音量已设置为 30% -2026-03-07 17:40:15,678 - INFO - 🔔 检测到远程连接断开 -``` - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-009: Windows 服务安装测试(可选) - -**目的**: 验证能安装为 Windows 服务 - -**前提**: 已下载 NSSM 工具 - -**步骤**: -```bash -# 以管理员身份运行 -nssm install RemoteVolumeMonitor "C:\Python39\python.exe" "C:\path\to\remote_volume_monitor.py" "--config" "C:\path\to\config.ini" -nssm set RemoteVolumeMonitor DisplayName "Remote Volume Monitor" -nssm set RemoteVolumeMonitor Start SERVICE_AUTO_START -nssm start RemoteVolumeMonitor -``` - -**预期结果**: -- ✅ 服务安装成功 -- ✅ 服务能正常启动 -- ✅ 开机自动启动 -- ✅ 服务状态可查询 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -### TC-010: 边界条件测试 - -**目的**: 验证极端条件下的稳定性 - -**测试项**: -1. 音量设置为 0% -2. 音量设置为 100% -3. 快速多次连接/断开 -4. 网络不稳定时 RDP 连接 -5. 多用户同时远程连接 - -**预期结果**: -- ✅ 0% 音量正常设置 -- ✅ 100% 音量正常设置 -- ✅ 快速切换无异常 -- ✅ 网络波动不影响程序稳定性 -- ✅ 多用户场景正常处理 - -**实际结果**: _______________ - -**测试人**: _______________ - -**日期**: _______________ - ---- - -## 📊 测试结果汇总 - -| 用例编号 | 测试项 | 结果 | 备注 | -|---------|--------|------|------| -| TC-001 | 依赖安装测试 | ⬜ 通过 ⬜ 失败 | | -| TC-002 | 程序启动测试 | ⬜ 通过 ⬜ 失败 | | -| TC-003 | 音量调节功能测试 | ⬜ 通过 ⬜ 失败 | | -| TC-004 | 远程连接检测测试 | ⬜ 通过 ⬜ 失败 | | -| TC-005 | 自动音量调节测试 | ⬜ 通过 ⬜ 失败 | | -| TC-006 | 配置文件测试 | ⬜ 通过 ⬜ 失败 | | -| TC-007 | 后台持续监控测试 | ⬜ 通过 ⬜ 失败 | | -| TC-008 | 日志记录测试 | ⬜ 通过 ⬜ 失败 | | -| TC-009 | Windows 服务安装测试 | ⬜ 通过 ⬜ 失败 ⬜ 跳过 | | -| TC-010 | 边界条件测试 | ⬜ 通过 ⬜ 失败 | | - -**总体结论**: ⬜ 通过 ⬜ 有条件通过 ⬜ 失败 - -**测试负责人**: _______________ - -**测试日期**: _______________ - -**审批人**: _______________ - ---- - -## 🐛 问题记录 - -### 问题 1 -**描述**: _______________ - -**严重程度**: ⬜ 严重 ⬜ 中 ⬜ 轻 - -**复现步骤**: _______________ - -**解决方案**: _______________ - -**状态**: ⬜ 待修复 ⬜ 修复中 ⬜ 已修复 ⬜ 已验证 - ---- - -### 问题 2 -**描述**: _______________ - -**严重程度**: ⬜ 严重 ⬜ 中 ⬜ 轻 - -**复现步骤**: _______________ - -**解决方案**: _______________ - -**状态**: ⬜ 待修复 ⬜ 修复中 ⬜ 已修复 ⬜ 已验证 - ---- - -## ✅ 验收标准 - -所有测试用例必须满足以下条件才能验收: - -- [ ] TC-001 ~ TC-008 全部通过 -- [ ] 无严重级别 Bug -- [ ] 中等级别 Bug < 3 个 -- [ ] 程序能稳定运行 24 小时 -- [ ] 文档完整可用 - ---- - -**测试完成后,请将此文档上传到飞书任务管理表的"交付物"字段!** diff --git a/Test/Scripts/test_rdp_detection.py b/Test/Scripts/test_rdp_detection.py deleted file mode 100644 index f73706a..0000000 --- a/Test/Scripts/test_rdp_detection.py +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -RDP 连接检测测试工具 -用于诊断 RDP 检测问题 -""" - -import os -import subprocess -import sys - - -def print_header(title): - print("\n" + "=" * 60) - print(f" {title}") - print("=" * 60) - - -def check_environment_variables(): - """检查环境变量""" - print_header("1. 环境变量检查") - - vars_to_check = [ - 'SESSIONNAME', - 'USERNAME', - 'USERDOMAIN', - 'COMPUTERNAME', - ] - - for var in vars_to_check: - value = os.environ.get(var, '(未设置)') - print(f" {var}: {value}") - - session_name = os.environ.get('SESSIONNAME', '') - if session_name.startswith('RDP'): - print(f"\n ✓ SESSIONNAME 以 RDP 开头,检测到远程会话") - return True - else: - print(f"\n ⚠ SESSIONNAME 不以 RDP 开头") - return False - - -def check_query_user(): - """检查 query user 命令输出""" - print_header("2. query user 命令检查") - - try: - result = subprocess.run( - ['query', 'user'], - capture_output=True, - text=True, - shell=True, - timeout=5 - ) - - print(f" 返回码:{result.returncode}") - print(f"\n 标准输出:") - for line in result.stdout.split('\n'): - print(f" {line}") - - if result.stderr: - print(f"\n 错误输出:") - for line in result.stderr.split('\n'): - print(f" {line}") - - # 分析输出 - output_lower = result.stdout.lower() - - print(f"\n 分析结果:") - - # 检查 RDP/TCP 关键字 - if 'rdp' in output_lower or 'tcp' in output_lower: - print(f" ✓ 包含 'rdp' 或 'tcp' 关键字") - - # 逐行检查 - for line in result.stdout.strip().split('\n'): - line_lower = line.lower() - if 'rdp' in line_lower or 'tcp' in line_lower: - if 'active' in line_lower: - print(f" ✓ 检测到活跃的 RDP/TCP 会话:{line.strip()}") - elif '>' in line: - print(f" ✓ 当前会话是 RDP/TCP:{line.strip()}") - else: - print(f" ⚠ 未包含 'rdp' 或 'tcp' 关键字") - - # 检查会话数量 - lines = [l for l in result.stdout.strip().split('\n') if l.strip() and not l.startswith(' ')] - if len(lines) > 1: - print(f" ⚠ 检测到 {len(lines)-1} 个会话(可能有多用户)") - - return True - - except FileNotFoundError: - print(f" ✗ query 命令不存在(仅在 Windows 上可用)") - return False - except Exception as e: - print(f" ✗ 执行失败:{e}") - return False - - -def check_registry(): - """检查注册表""" - print_header("3. 注册表检查") - - try: - import winreg - - # 检查 Terminal Server 设置 - try: - key = winreg.OpenKey( - winreg.HKEY_LOCAL_MACHINE, - r"SYSTEM\CurrentControlSet\Control\Terminal Server" - ) - - try: - val, _ = winreg.QueryValueEx(key, "fDenyTSConnections") - if val == 0: - print(f" ✓ 终端服务已启用") - else: - print(f" ⚠ 终端服务被禁用") - except: - print(f" ⚠ 无法读取 fDenyTSConnections") - - winreg.CloseKey(key) - except Exception as e: - print(f" ⚠ Terminal Server 键值访问失败:{e}") - - # 检查当前会话 - try: - key = winreg.OpenKey( - winreg.HKEY_CURRENT_USER, - r"Volatile Environment" - ) - print(f" ✓ 当前用户环境键可访问") - winreg.CloseKey(key) - except: - print(f" ⚠ 当前用户环境键访问失败") - - return True - - except ImportError: - print(f" ⚠ winreg 模块不可用(非 Windows 系统?)") - return False - except Exception as e: - print(f" ✗ 检查失败:{e}") - return False - - -def check_network(): - """检查网络连接""" - print_header("4. 网络连接检查") - - try: - result = subprocess.run( - ['netstat', '-an'], - capture_output=True, - text=True, - shell=True, - timeout=5 - ) - - output_lower = result.stdout.lower() - - # 检查 RDP 端口 3389 - if '3389' in output_lower: - print(f" ✓ 检测到 RDP 端口 (3389) 活动") - - # 统计连接数 - lines = output_lower.split('\n') - rdp_connections = [l for l in lines if '3389' in l and 'established' in l] - if rdp_connections: - print(f" ✓ 发现 {len(rdp_connections)} 个 RDP 连接:") - for conn in rdp_connections[:5]: # 最多显示 5 个 - print(f" {conn.strip()}") - else: - print(f" ⚠ 未检测到 RDP 端口 (3389) 活动") - - return True - - except Exception as e: - print(f" ✗ 检查失败:{e}") - return False - - -def main(): - print("\n") - print("╔" + "═" * 58 + "╗") - print("║" + " " * 15 + "RDP 连接检测诊断工具" + " " * 15 + "║") - print("╚" + "═" * 58 + "╝") - - print(f"\n 计算机名:{os.environ.get('COMPUTERNAME', 'Unknown')}") - print(f" 用户名:{os.environ.get('USERNAME', 'Unknown')}") - print(f" 时间:{subprocess.run(['date'], capture_output=True, text=True, shell=True).stdout.strip()}") - - # 执行各项检查 - env_result = check_environment_variables() - query_result = check_query_user() - registry_result = check_registry() - network_result = check_network() - - # 总结 - print_header("诊断总结") - - if env_result: - print(" ✓ 环境变量检测到 RDP 会话") - print("\n 建议:程序应该能检测到 RDP 连接") - elif query_result: - print(" ⚠ 环境变量未检测到,但 query user 可能有信息") - print("\n 建议:检查 query user 输出中的 RDP/TCP 关键字") - else: - print(" ✗ 未检测到 RDP 会话特征") - print("\n 可能原因:") - print(" 1. 当前是本地登录,不是 RDP 远程连接") - print(" 2. RDP 连接已断开") - print(" 3. 终端服务被禁用") - print(" 4. 使用了其他远程工具(如 TeamViewer、AnyDesk)") - - print("\n 测试完成!") - print("\n") - - # 返回结果 - if env_result or query_result: - sys.exit(0) # 检测到 RDP - else: - sys.exit(1) # 未检测到 RDP - - -if __name__ == '__main__': - main() diff --git a/Test/Scripts/test_rdp_disconnect.py b/Test/Scripts/test_rdp_disconnect.py deleted file mode 100644 index 0e93746..0000000 --- a/Test/Scripts/test_rdp_disconnect.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -RDP 断开检测测试工具 -专门测试 RDP 断开后的检测逻辑 -""" - -import subprocess -import os - - -def check_query_user(): - """检查 query user 输出""" - print("\n" + "=" * 60) - print(" query user 命令输出") - print("=" * 60) - - try: - result = subprocess.run( - ['query', 'user'], - capture_output=True, - text=True, - shell=True, - timeout=5 - ) - - print(f"\n{result.stdout}") - - if result.stderr: - print(f"错误:{result.stderr}") - - # 详细分析 - print("\n" + "=" * 60) - print(" 详细分析") - print("=" * 60) - - lines = result.stdout.strip().split('\n') - - for i, line in enumerate(lines): - line_stripped = line.strip() - line_lower = line_stripped.lower() - - if not line_stripped: - continue - - print(f"\n第 {i+1} 行:{line_stripped}") - - # 检查标记 - markers = [] - if '>' in line_stripped: - markers.append("✓ 当前会话") - if 'rdp' in line_lower: - markers.append("RDP 连接") - if 'tcp' in line_lower: - markers.append("TCP 连接") - if 'active' in line_lower: - markers.append("活跃状态") - if 'disc' in line_lower: - markers.append("已断开") - if 'Console' in line_stripped or 'console' in line_lower: - markers.append("控制台") - - if markers: - print(f" 标记:{', '.join(markers)}") - - # 判断 - if '>' in line_stripped: - if 'active' in line_lower and ('rdp' in line_lower or 'tcp' in line_lower): - print(f" → 结论:当前是活跃的 RDP 连接") - elif 'disc' in line_lower and ('rdp' in line_lower or 'tcp' in line_lower): - print(f" → 结论:RDP 已断开,应恢复本地音量") - elif 'Console' in line_stripped: - print(f" → 结论:本地控制台会话") - else: - print(f" → 结论:未知状态") - - return True - - except FileNotFoundError: - print("✗ query 命令不存在(仅在 Windows 上可用)") - return False - except Exception as e: - print(f"✗ 执行失败:{e}") - return False - - -def check_sessionname(): - """检查 SESSIONNAME 环境变量""" - print("\n" + "=" * 60) - print(" 环境变量检查") - print("=" * 60) - - session_name = os.environ.get('SESSIONNAME', '(未设置)') - username = os.environ.get('USERNAME', '(未设置)') - - print(f"\nSESSIONNAME: {session_name}") - print(f"USERNAME: {username}") - - if session_name.startswith('RDP'): - print(f"\n⚠ SESSIONNAME 以 RDP 开头") - print(f" 但这可能是已断开的会话,需要结合 query user 判断") - elif session_name == 'Console': - print(f"\n✓ SESSIONNAME 是 Console,本地会话") - else: - print(f"\n? SESSIONNAME 未知格式") - - return session_name - - -def main(): - print("\n") - print("╔" + "═" * 58 + "╗") - print("║" + " " * 12 + "RDP 断开检测诊断工具" + " " * 12 + "║") - print("╚" + "═" * 58 + "╝") - - print("\n此工具用于诊断 RDP 断开后的检测问题") - print("适用于:断开 RDP 后程序仍显示远程连接的情况") - - # 检查 - session_name = check_sessionname() - check_query_user() - - # 总结 - print("\n" + "=" * 60) - print(" 诊断总结") - print("=" * 60) - - print("\n📋 判断规则:") - print(" 1. 当前会话(带 >)+ active + RDP/TCP = 活跃远程连接") - print(" 2. 当前会话(带 >)+ disc + RDP/TCP = 已断开,应恢复音量") - print(" 3. 当前会话(带 >)+ Console = 本地会话") - print(" 4. 无活跃 RDP 会话 = 本地状态") - - print("\n💡 如果断开 RDP 后仍显示远程连接:") - print(" - 检查是否有 'disc' 标记被误判为 'active'") - print(" - 检查是否有多个会话(一个断开 + 一个活跃)") - print(" - 查看上方详细分析,确认哪一行被判定为远程") - - print("\n✅ 测试完成!") - print("\n") - - -if __name__ == '__main__': - main()