PythonでWindows上のウィンドウフォーカスの移動を常に監視し、変更があれば今アクティブなウィンドウの名前とプロセス名を取得し表示するプログラムを作成することはできますか。なお実行環境はCUIでとします

はい、Pythonを使ってWindows上のウィンドウフォーカスの移動を監視し、アクティブなウィンドウの名前とプロセス名を取得して表示するプログラムを作成することができます。以下はそのためのサンプルコードです。

import time
import win32gui
import win32process
import psutil

def get_active_window_info():
    hwnd = win32gui.GetForegroundWindow()
    _, pid = win32process.GetWindowThreadProcessId(hwnd)
    process = psutil.Process(pid)
    window_title = win32gui.GetWindowText(hwnd)
    process_name = process.name()
    return window_title, process_name

def main():
    last_window = None
    while True:
        current_window = get_active_window_info()
        if current_window != last_window:
            print(f"Active Window: {current_window[0]}, Process: {current_window[1]}")
            last_window = current_window
        time.sleep(1)

if __name__ == "__main__":
    main()

このプログラムは、1秒ごとにアクティブなウィンドウの情報を取得し、ウィンドウが変更された場合にその情報を表示します。pywin32psutilというライブラリが必要ですので、以下のコマンドでインストールしてください。

pip install pywin32 psutil

何か他に質問があれば教えてください!

実行してみたところ、まれにPIDの取得に失敗したりプロセス情報の取得に失敗することがあります。

これらの情報の取得に失敗したときはプログラムを強制終了させず、赤文字でプロセスの情報取得に失敗した旨を表示し以降の処理を続行するよう修正してください

了解しました。以下のように修正してみてください。

import os
import psutil

def get_process_info(pid):
    try:
        process = psutil.Process(pid)
        return process
    except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
        print("\\033[91mプロセスの情報取得に失敗しました\\033[0m")
        return None

def main():
    pid = os.getpid()
    process_info = get_process_info(pid)
    if process_info:
        # プロセス情報の処理を続行
        print(f"プロセス名: {process_info.name()}")
        print(f"プロセスID: {process_info.pid}")
    else:
        # プロセス情報の取得に失敗した場合の処理
        print("プロセス情報の取得に失敗しましたが、プログラムは続行します。")

if __name__ == "__main__":
    main()

この修正では、プロセス情報の取得に失敗した場合に赤文字でエラーメッセージを表示し、プログラムの実行を続行するようにしています。試してみてください。何か他にお手伝いできることがあれば教えてくださいね。

以下の修正を行ってください

了解しました。以下のように修正してみてください。アクティブなウィンドウのタイトルとプロセス名を1秒ごとに取得し続けるコードです。

import time
import psutil
import win32gui
import win32process

def get_active_window_info():
  try:
    hwnd = win32gui.GetForegroundWindow()
    _, pid = win32process.GetWindowThreadProcessId(hwnd)
    process = psutil.Process(pid)
    window_title = win32gui.GetWindowText(hwnd)
    return window_title, process.name()
  except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
    print("\\033[91mウィンドウ情報の取得に失敗しました\\033[0m")
    return None, None

def main():
  while True:
    window_title, process_name = get_active_window_info()
    if window_title and process_name:
      print(f"ウィンドウタイトル: {window_title}")
      print(f"プロセス名: {process_name}")
    else:
      print("ウィンドウ情報の取得に失敗しましたが、プログラムは続行します。")
    time.sleep(1)

if __name__ == "__main__":
  main()

このコードでは、1秒ごとにアクティブなウィンドウのタイトルとプロセス名を取得し、表示します。インデントはスペース2個で統一しています。試してみてください。何か他にお手伝いできることがあれば教えてくださいね。