You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python记录Windows中各类软件打开的文件路径?

用Python追踪软件打开的文件路径并记录时间戳

需求可行性说明

这个需求完全可行,针对Windows平台,可以通过进程监控、系统API调用结合窗口信息解析的方式实现。核心思路是:

  • 通过psutil获取进程的已打开文件句柄
  • 通过Windows API(win32gui/win32process)获取窗口信息,补充psutil无法捕获的场景(比如文件资源管理器的当前浏览路径)
  • 为捕获到的文件信息添加时间戳,实现持久化记录

现有AI生成代码的分析

你提供的代码已经实现了基础的进程文件监控,但存在几个局限性:

  1. psutil.open_files()的局限性:部分软件(如VS Code的标签页文件)不会通过常规文件句柄暴露,无法被捕获;文件资源管理器的当前浏览路径也无法通过该方法获取。
  2. 仅内存记录:重启程序后追踪的历史记录会丢失,没有持久化存储。
  3. 权限问题:部分系统进程或高权限进程会拒绝访问,需要以管理员身份运行脚本。

优化后的实现代码

以下是补充了特定软件适配、持久化记录的优化版本:

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)

关键优化点说明

  1. 文件资源管理器适配:通过枚举窗口标题解析当前浏览的文件夹路径,弥补psutil无法获取该信息的缺陷。
  2. 持久化存储:将追踪记录保存到JSON文件,重启程序后可继续追踪。
  3. 路径有效性校验:通过Path.exists()过滤无效路径,避免错误记录。
  4. 权限提示:运行脚本时建议以管理员身份启动,避免部分进程访问被拒绝。

注意事项

  • 平台限制:该方案仅适用于Windows系统,因为用到了win32gui等Windows专属API。
  • 软件兼容性:部分软件(如VS Code的远程文件)无法通过此方法捕获,若需支持可结合VS Code的REST API实现。
  • 性能影响:缩短追踪间隔会增加系统资源占用,建议根据需求设置合理的间隔时间。

内容的提问来源于stack exchange,提问作者Jack445

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 18:13:10