如何用Python记录Windows中各类软件打开的文件路径?
用Python追踪软件打开的文件路径并记录时间戳
需求可行性说明
这个需求完全可行,针对Windows平台,可以通过进程监控、系统API调用结合窗口信息解析的方式实现。核心思路是:
- 通过
psutil获取进程的已打开文件句柄 - 通过Windows API(
win32gui/win32process)获取窗口信息,补充psutil无法捕获的场景(比如文件资源管理器的当前浏览路径) - 为捕获到的文件信息添加时间戳,实现持久化记录
现有AI生成代码的分析
你提供的代码已经实现了基础的进程文件监控,但存在几个局限性:
psutil.open_files()的局限性:部分软件(如VS Code的标签页文件)不会通过常规文件句柄暴露,无法被捕获;文件资源管理器的当前浏览路径也无法通过该方法获取。- 仅内存记录:重启程序后追踪的历史记录会丢失,没有持久化存储。
- 权限问题:部分系统进程或高权限进程会拒绝访问,需要以管理员身份运行脚本。
优化后的实现代码
以下是补充了特定软件适配、持久化记录的优化版本:
import psutil import win32gui import win32process import time import json from datetime import datetime from pathlib import Path class FileTracker: def __init__(self, log_file="tracked_files.json"): # 目标进程映射:进程名 -> 软件名称 self.target_processes = { 'explorer.exe': '文件资源管理器', 'Code.exe': 'VS Code', 'EXCEL.EXE': 'Excel', 'AcroRd32.exe': 'Adobe Reader', 'Acrobat.exe': 'Adobe Acrobat' } self.tracked_files = {} self.log_file = Path(log_file) # 加载已有的记录 self._load_existing_logs() def _load_existing_logs(self): """加载之前保存的追踪记录""" if self.log_file.exists(): with open(self.log_file, 'r', encoding='utf-8') as f: self.tracked_files = json.load(f) # 转换为集合方便去重 for proc in self.tracked_files: self.tracked_files[proc] = set(self.tracked_files[proc]) else: for proc_name in self.target_processes: self.tracked_files[proc_name] = set() def _save_logs(self): """将追踪记录保存到JSON文件""" # 转换为列表以便JSON序列化 save_data = {k: list(v) for k, v in self.tracked_files.items()} with open(self.log_file, 'w', encoding='utf-8') as f: json.dump(save_data, f, ensure_ascii=False, indent=2) def _get_explorer_current_path(self): """获取文件资源管理器当前打开的文件夹路径""" def callback(hwnd, extra): if win32gui.GetWindowText(hwnd): _, pid = win32process.GetWindowThreadProcessId(hwnd) try: proc = psutil.Process(pid) if proc.name() == 'explorer.exe': window_text = win32gui.GetWindowText(hwnd) # 解析窗口标题获取路径,排除桌面等特殊窗口 if ' - 文件资源管理器' in window_text: path = window_text.replace(' - 文件资源管理器', '') if Path(path).exists(): extra.add(path) except (psutil.NoSuchProcess, psutil.AccessDenied): pass return True paths = set() win32gui.EnumWindows(callback, paths) return paths def get_open_files(self): current_files = {} # 处理通用进程的打开文件 for proc in psutil.process_iter(['pid', 'name']): try: proc_name = proc.info['name'] if proc_name in self.target_processes: app_name = self.target_processes[proc_name] files = [] # 针对文件资源管理器单独处理 if proc_name == 'explorer.exe': files = list(self._get_explorer_current_path()) else: # 获取进程打开的文件 proc_files = proc.open_files() files = [f.path for f in proc_files if Path(f.path).exists()] if files: current_files[proc_name] = { 'app_name': app_name, 'files': files, 'timestamp': datetime.now().isoformat() } except (psutil.NoSuchProcess, psutil.AccessDenied): continue return current_files def track_continuously(self, interval=5): """每隔interval秒追踪一次文件""" print(f"开始追踪,间隔{interval}秒,记录保存到{self.log_file}") while True: current_files = self.get_open_files() # 记录新打开的文件 for proc_name, data in current_files.items(): for file_path in data['files']: if file_path not in self.tracked_files[proc_name]: print(f"[{data['timestamp']}] {data['app_name']} 打开了文件: {file_path}") self.tracked_files[proc_name].add(file_path) # 实时保存记录 self._save_logs() time.sleep(interval) # 运行示例 if __name__ == "__main__": tracker = FileTracker() print("当前已打开的文件:") files = tracker.get_open_files() for proc, data in files.items(): print(f"\n{data['app_name']} ({proc}):") for file_path in data['files']: print(f" - {file_path}") # 开始持续追踪 tracker.track_continuously(interval=5)
关键优化点说明
- 文件资源管理器适配:通过枚举窗口标题解析当前浏览的文件夹路径,弥补
psutil无法获取该信息的缺陷。 - 持久化存储:将追踪记录保存到JSON文件,重启程序后可继续追踪。
- 路径有效性校验:通过
Path.exists()过滤无效路径,避免错误记录。 - 权限提示:运行脚本时建议以管理员身份启动,避免部分进程访问被拒绝。
注意事项
- 平台限制:该方案仅适用于Windows系统,因为用到了
win32gui等Windows专属API。 - 软件兼容性:部分软件(如VS Code的远程文件)无法通过此方法捕获,若需支持可结合VS Code的REST API实现。
- 性能影响:缩短追踪间隔会增加系统资源占用,建议根据需求设置合理的间隔时间。
内容的提问来源于stack exchange,提问作者Jack445
相关产品推荐
相关产品推荐

