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

Python窗口时间追踪程序异常:工作时chrome/edge进程同时出现

问题描述

我工作时容易分心,常被YouTube、WhatsApp这类应用干扰,因此开发了一款追踪时间的Python应用,但遇到问题:当我在Python编程窗口工作时,程序却同时显示chrome.exe和msedge.exe进程,找不到问题根源,特此求助。

附代码:

import time
import pygetwindow as gw
import win32gui
import win32process
import psutil
import requests

def get_active_application(title):
    try:
        hwnd = win32gui.FindWindow(None, title)
        threadid, pid = win32process.GetWindowThreadProcessId(hwnd)
        process = psutil.Process(pid)
        process_name = process.name()
        return process_name
    except Exception as e:
        print(f"Error in get_active_application: {e}")
        return None

def post_data(user, window_title, window_application, elapsed_time):
    if elapsed_time > 5:
        url = "MyServerPath.php"
        json_data = {
            "user": user,
            "window_title": window_title,
            "window_application": window_application,
            "elapsed_time": int(elapsed_time)
        }
        try:
            response = requests.post(url, json=json_data)
            response.raise_for_status()  # Raise an error for bad responses (4xx or 5xx)
            print(f"USER: {user} Time spent in {window_title} ({window_application}): {int(elapsed_time)} seconds")
        except requests.RequestException as e:
            print("POST request failed:", e)

def log_window_focus(user):
    window_logs = {}

    try:
        while True:
            current_window = gw.getActiveWindow()
            if current_window is not None:
                window_title = current_window.title
                window_application = get_active_application(window_title)

                if window_title not in window_logs:
                    window_logs[window_title] = {"time_spent": 0, "application": window_application}

                start_time = time.time()

                while gw.getActiveWindow() is not None and gw.getActiveWindow().title == window_title:
                    time.sleep(1)

                elapsed_time = time.time() - start_time
                window_logs[window_title]["time_spent"] += elapsed_time
                post_data(user, window_title, window_application, elapsed_time)

    except KeyboardInterrupt:
        print("\nPuta Sumario")
        for window, data in window_logs.items():
            print(f"{window} ({data['application']}): {data['time_spent']} seconds")

if __name__ == "__main__":
    user = "usertest"
    log_window_focus(user)

进程显示异常截图

问题原因

当前代码通过win32gui.FindWindow(None, title)根据窗口标题查找句柄,但不同进程的窗口可能有相同的标题(比如浏览器标签页标题和编程工具窗口标题重复),这会导致你拿到的不是当前激活窗口的句柄,而是其他进程(比如Chrome/Edge)的窗口句柄,进而返回错误的进程名。

解决方案

直接使用pygetwindow返回的激活窗口对象自带的句柄(_hWnd属性),而不是通过标题查找,这样能确保获取的是当前激活窗口对应的进程。

修改后的代码如下:

import time
import pygetwindow as gw
import win32process
import psutil
import requests

def get_active_application(hwnd):
    try:
        threadid, pid = win32process.GetWindowThreadProcessId(hwnd)
        process = psutil.Process(pid)
        process_name = process.name()
        return process_name
    except Exception as e:
        print(f"Error in get_active_application: {e}")
        return None

def post_data(user, window_title, window_application, elapsed_time):
    if elapsed_time > 5:
        url = "MyServerPath.php"
        json_data = {
            "user": user,
            "window_title": window_title,
            "window_application": window_application,
            "elapsed_time": int(elapsed_time)
        }
        try:
            response = requests.post(url, json=json_data)
            response.raise_for_status()  # Raise an error for bad responses (4xx or 5xx)
            print(f"USER: {user} Time spent in {window_title} ({window_application}): {int(elapsed_time)} seconds")
        except requests.RequestException as e:
            print("POST request failed:", e)

def log_window_focus(user):
    window_logs = {}

    try:
        while True:
            current_window = gw.getActiveWindow()
            if current_window is not None:
                window_title = current_window.title
                # 直接使用当前激活窗口的句柄
                window_application = get_active_application(current_window._hWnd)

                if window_title not in window_logs:
                    window_logs[window_title] = {"time_spent": 0, "application": window_application}

                start_time = time.time()

                while gw.getActiveWindow() is not None and gw.getActiveWindow().title == window_title:
                    time.sleep(1)

                elapsed_time = time.time() - start_time
                window_logs[window_title]["time_spent"] += elapsed_time
                post_data(user, window_title, window_application, elapsed_time)

    except KeyboardInterrupt:
        print("\nPuta Sumario")
        for window, data in window_logs.items():
            print(f"{window} ({data['application']}): {data['time_spent']} seconds")

if __name__ == "__main__":
    user = "usertest"
    log_window_focus(user)
关键修改点
  • 调整get_active_application函数的参数,从接收窗口标题改为接收窗口句柄hwnd
  • 在log_window_focus中,直接传入current_window._hWnd到get_active_application,确保获取的是当前激活窗口的进程信息

内容的提问来源于stack exchange,提问作者Mário Jorge Rocha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:27:28