FontSepten
@FontSepten
Любитель

Получение количества открытых окон через WinApi?

Я пишу проект для проведения экзаменов в одном учебном заведении. Мне хотелось бы иметь возможность получения количества открытых окон других программ, для защиты академической честности (останавливать тест если открыл второе приложение, калькулятора или браузера и т.д.).

Я пытался реализовать это по этому вопросу на stackoverflow
https://stackoverflow.com/questions/10246444/how-c...
но этот метод работает неправильно, также показывая количество и скрытых окон.

Ответ можно в C/C++ или Rust (на крайняк Python)
  • Вопрос задан
  • 1030 просмотров
Решения вопроса 1
@antares4045
Учитывая, что код на питоне принимается "на крайняк", не уверен, что это можно считать полноценным ответом: на питоне есть такая презамечательная либа: psutil при помощи которой я переодически пишу всякую грязь опираясь на шаблон
import psutil
import win32gui
import win32process


def enum_window_callback(hwnd, pid):
        tid, current_pid = win32process.GetWindowThreadProcessId(hwnd)
        if pid == current_pid and win32gui.IsWindowVisible(hwnd):
            windows.append(hwnd)

for process in psutil.process_iter():
    pid = process.pid
    windows = []
    win32gui.EnumWindows(enum_window_callback, pid)
    windownames = [win32gui.GetWindowText(item) for item in windows]
    
    if len(windownames):
        exeName = process.name()
        for windowName in windownames:
            hwnd = win32gui.FindWindow(None, windowName)
            print(f'"{exeName}" - "{windowName}" - "{hwnd}"')

Вывод:
"NVIDIA Share.exe" - "NVIDIA GeForce Overlay" - "66250"
"Code.exe" - "list of windows.py - grabscrren - Visual Studio Code" - "459882"
"Code.exe" - "● N-mer-Krammer.py - Рандомный habr - Visual Studio Code" - "132316"
"Battle.net.exe" - "Battle.net" - "132384"
"explorer.exe" - "" - "65860"
"explorer.exe" - "D:\" - "263030"
"explorer.exe" - "" - "65860"
"explorer.exe" - "" - "65860"
"explorer.exe" - "" - "65860"
"explorer.exe" - "" - "65860"
"explorer.exe" - "Program Manager" - "131380"
"python.exe" - "Jupyter Notebook" - "1639536"
"chrome.exe" - "Получение количества открытых окон через WinApi? — Хабр Q&A - Google Chrome" - "1442268"


На выходе имеем список формата запущенный экзешник - имя окна - pid
для вашей задачи если вам не нравится какой-либо экзешник -- можете банить.

но с трансляцией в плюсы есть проблема: psutil (я пытался разобраться пару лет назад) под капотом творит какую-то чёрную магию, так что единственное, что могу вам предложить, это скомпилировать этот скрипт в отдельный экзешник и вызывать его субпроцессом (ну или игнорировать мой ответ).

Правда если вы знаете способ (вдруг), как под виндой получить список всех pid, то поделитесь -- буду очень рад.

UPD:
не смог отпустить и сделал реализацию полностью на winapi
import win32gui
import win32process
import win32api
import win32process
import win32con


def enum_window_callback(hwnd, _):
        if win32gui.IsWindowVisible(hwnd):
            tid, current_pid = win32process.GetWindowThreadProcessId(hwnd)
            handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION | win32con.PROCESS_VM_READ, False, current_pid)
            proc_name = win32process.GetModuleFileNameEx(handle, 0)
            windows.append({
                "hwnd":hwnd, 
                "pid" : current_pid, 
                "tid" : tid,
                "window title" : win32gui.GetWindowText(hwnd),
                "process name" : proc_name
                })

windows = []

win32gui.EnumWindows(enum_window_callback, None)

for window in windows:
    print(f'"{window["process name"]}"', window['pid'], f'"{window["window title"]}"', window['hwnd'], sep=' - ')

Вывод:
"C:\Windows\explorer.exe" - 8084 - "" - 65736
"C:\Users\Тоха\AppData\Local\Programs\Microsoft VS Code\Code.exe" - 6124 - "list of windows.py - grabscrren - Visual Studio Code" - 459882
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" - 11696 - "windows - How can I get process name using Python - Stack Overflow - Google Chrome" - 131222
"C:\Users\Тоха\AppData\Local\Programs\Microsoft VS Code\Code.exe" - 6124 - "● N-mer-Krammer.py - Рандомный habr - Visual Studio Code" - 132316
"C:\Qt\Tools\QtCreator\bin\qtcreator.exe" - 11308 - "main.cpp @ processScan - Qt Creator" - 1967294
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" - 11696 - "Получение количества открытых окон через WinApi? — Хабр Q&A - Google Chrome" - 1442268
"C:\Anaconda3\python.exe" - 9912 - "Jupyter Notebook" - 1639536
"C:\Program Files (x86)\Battle.net\Battle.net.exe" - 6396 - "Battle.net" - 132384
"C:\Windows\explorer.exe" - 8084 - "D:\" - 263030
"C:\Windows\SystemApps\MicrosoftWindows.Client.CBS_cw5n1h2txyewy\InputApp\TextInputHost.exe" - 12956 - "Microsoft Text Input Application" - 131658
"C:\Program Files\NVIDIA Corporation\NVIDIA GeForce Experience\NVIDIA Share.exe" - 5488 - "NVIDIA GeForce Overlay" - 66250
"C:\Windows\explorer.exe" - 8084 - "" - 65924
"C:\Windows\explorer.exe" - 8084 - "" - 65932
"C:\Windows\explorer.exe" - 8084 - "" - 65892
"C:\Windows\explorer.exe" - 8084 - "" - 65890
"C:\Windows\explorer.exe" - 8084 - "Program Manager" - 131380

При переносе на плюсы столкнулся с тем, что не помню, как нормально импортировать всех этих винюзеров -- если напишете скиньте в комметарии, а мне надоело)
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы