diff --git a/Releases/remote-volume-monitor-v1.0.zip b/Releases/remote-volume-monitor-v1.0.zip deleted file mode 100644 index f2ce563..0000000 Binary files a/Releases/remote-volume-monitor-v1.0.zip and /dev/null differ 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()