Как узнать, открыта ли программа

В настоящее время я автоматизирую процесс, включающий запуск Hapfacs 3.0, программы C#, предназначенной для создания изображений лица. Я использую python, чтобы открыть программу, установить некоторые параметры, а затем сохранить полученное изображение. Автоматика сделает этот процесс 1000 раз. Процесс сохранения включает в себя открытие Проводника (у меня Windows 7), ввод имени файла и сохранение.

Одна проблема, с которой я сталкиваюсь, заключается в том, что для открытия File Explorer иногда требуется некоторое время, что мешает автоматизации, поскольку программа начинает вводить имя файла до того, как окно File Explorer открыто.

Я бы хотел, чтобы программа ждала, пока откроется проводник, прежде чем она начнет печатать. Таким образом, мне нужно иметь возможность определить, открыт ли проводник. Я нашел эту страницу здесь:

Python проверяет, запущен процесс или нет

который предлагает использовать модуль psutil:

import psutil    
"someProgram" in (p.name() for p in psutil.process_iter())

Однако список

[p.name() for p in psutil.process_iter()]

не отличается, если File Explorer открыт по сравнению с тем, когда он закрыт, предполагая, что File Explorer никогда не добавляется в список. Могу ли я проверить, открыт ли File Explorer с помощью psutil, или есть другой способ достичь моей цели? Спасибо за вашу помощь.


person Spencer Reschke    schedule 20.08.2018    source источник
comment
Проводник почти всегда открыт. Когда вы просите Windows, например, explore C:\Spam, программа explore.exe запускается, находит существующий процесс File Explorer, сообщает ему открыть окно для C:\Spam, а затем завершает работу. Таким образом, после того, как это будет сделано, набор запущенных процессов обычно будет точно таким же, как и раньше.   -  person abarnert    schedule 21.08.2018
comment
Итак, как мне узнать, открыто ли окно Проводника? Код explorer.exe в [p.name() for p в psutil.process_iter()] оценивает значение True независимо от того, открыто окно Проводника или нет.   -  person Spencer Reschke    schedule 21.08.2018
comment
Если открыто любое окно? Или любое окно, которое переместилось в какой-то конкретный каталог? Или какое-то конкретное окно, которое вы можете идентифицировать каким-то образом, который вы еще не объяснили?   -  person abarnert    schedule 21.08.2018
comment
Да, конечно, это правда. Как я уже сказал, File Explorer почти всегда открыт, поэтому его почти всегда можно найти в process_iter.   -  person abarnert    schedule 21.08.2018
comment
Если бы я мог определить, открыто ли окно File Explorer, которое находится в определенном каталоге, это сработало бы.   -  person Spencer Reschke    schedule 21.08.2018
comment
Не просто любое окно, ваш рабочий стол открыт? explorer — это процесс, который отображает ваш рабочий стол — когда он дает сбой, ваша панель задач, значки и другие элементы на вашем рабочем столе обычно исчезают (и это только самое заметное изменение).   -  person LinkBerest    schedule 21.08.2018
comment
Пожалуйста, не помечайте заголовок вопроса языком программирования - для этого нужны настоящие теги. редактирование.   -  person xaxxon    schedule 21.08.2018
comment
Я думаю, что вы на самом деле хотите сделать одно из следующего (от наиболее идеального вниз): (1) не используйте проводник; (2) использовать проводник через Win32COM вместо подпроцесса; (3) использовать проводник с каким-либо флагом, который заставляет его открывать новый процесс; (4) перечислите все окна с помощью PyWin32 и найдите то, у которого есть владелец, класс и имя, которые вам нужны. (Существует или, по крайней мере, когда-то был инструмент, называемый чем-то вроде WinSpy, который поставляется с бесплатной версией Visual Studio и позволяет вам проверять существующие окна и видеть, как должны выглядеть значения.)   -  person abarnert    schedule 21.08.2018


Ответы (2)


К сожалению для вас, причина, по которой вы не можете найти ничего изменяющегося, заключается в том, что в Windows «explorer.exe», который отвечает практически за все операции с файлами (файловый проводник, управление рабочим столом и т. д.), всегда открыт и запускается из единичный экземпляр. Я не знаю, как вы можете сделать это из python, но у меня есть решение, которое вы можете включить, даже если оно не идеально.

Используя PIL, можно найти здесь http://www.pythonware.com/products/pil/. , вы можете получить изображение экрана и проверить цвета пикселей в определенных точках, что должно позволить то, что вам нужно в данный момент. Если вам нужно захватить цвета пикселей с экрана, лучшим инструментом, который я могу придумать для быстрых макетов, будет autohotkeys window spy.

Надеюсь, это поможет, я знаю, как иногда может раздражать автоматизация, когда вам приходится делать подобные хаки, поэтому дайте мне знать, если у вас есть другие вопросы.

Правка: я размышлял над идеей, что когда проводник открыт, количество дескрипторов, открытых проводником, увеличится с приличным отрывом, и если вы этого не сделаете, все, кроме запуска автоматических сценариев, поведение довольно предсказуемо, но потребует небольшого эксперимента с вашей стороны.

Вот что у меня есть:

import psutil
for proc in psutil.process_iter():
    if 'explorer' in proc.name():
        print(proc.name() + " handles:" + str(proc.num_handles()))

Когда я запускаю это с закрытым проводником по сравнению с открытым проводником, я получаю случайное увеличение примерно на 100 дескрипторов или более, поэтому вы можете сохранить предыдущее количество и опросить текущее количество при условии, что вы ничего не открываете. когда количество дескрипторов увеличивается на X, вы знаете, что проводник был открыт и может начать печатать, затем, когда он упадет до X, вы знаете, что он закрыт, и вы повторно сохраняете новый счетчик дескрипторов и снова ждете увеличения X.

Хотя это не идеальное решение, вы должны быть в состоянии заставить его работать достаточно хорошо для того, что вы хотите.

Редактировать2:

Это работает для меня, вам может потребоваться изменить значение normalIncrease, так как это может быть большее или меньшее количество созданных дескрипторов.

import psutil
import time


handlesPrevious = 0
usualIncrease = 100

for proc in psutil.process_iter():
    if 'explorer' in proc.name():
        handlesPrevious = proc.num_handles()

while 1:
    time.sleep(5)
    for proc in psutil.process_iter():
        if 'explorer' in proc.name():
            handlesCurrent = proc.num_handles()
            if (handlesPrevious + usualIncrease) <= handlesCurrent:
                print("File explorer open! - handles:" + str(handlesCurrent) + " previous handles:" + str(handlesPrevious))
                handlesPrevious = handlesCurrent
            elif (handlesPrevious - usualIncrease) > handlesCurrent:
                print("File explorer not open! - handles:" + str(handlesCurrent))
                handlesPrevious = handlesCurrent
person vividpk21    schedule 20.08.2018
comment
Как знание цвета пикселя в определенной точке скажет вам, было ли открыто какое-то окно проводника (даже если ОП может выяснить, как определить, какое окно он ищет в первую очередь)? - person abarnert; 21.08.2018
comment
Это просто базовая автоматизация, предположим, что у вас есть экран проводника файлов и экран меню для вашей программы, когда вы открываете проводник файлов, пиксель во многих местах на экране изменится, потому что новое окно помещается поверх старого и вы просто выбираете произвольное место. Но независимо от этого я обновил свой пост несколько лучшим (более быстрым) решением. - person vividpk21; 21.08.2018
comment
@ vividpk21 Мне это нравится больше, чем использование PIL, поскольку PIL в настоящее время не поддерживает python 3+ (я использую python 3.6). Я попробую ваше второе предложение и дам вам знать, как оно работает. - person Spencer Reschke; 21.08.2018
comment
@SpencerReschke Pillow — это современная версия PIL, и она определенно поддерживает Python 3 (фактически, в следующей версии Python 2 переходит на устаревшую поддержку). - person abarnert; 21.08.2018
comment
Я написал небольшой тест, и он работает, я снова отредактировал вышеприведенное с помощью моего простого макета, если вы хотите его протестировать. - person vividpk21; 21.08.2018
comment
Глядя на группу случайных пикселей, чтобы увидеть, изменились ли какие-либо из них, можно легко получить как ложные негативы (легко возможно, что новое окно не перекрывает ни один из этих пикселей), так и ложные срабатывания (например, часы меняются каждую секунду). , некоторые из ваших окон могут отображать хвост или анимацию…). - person abarnert; 21.08.2018
comment
Как я уже сказал, это не идеально, но оно выполняет свою работу. Я написал сложные программы для создания игровых ботов, используя autohotkey, которые используют эту технику, и все это методом проб и ошибок. Очевидно, что есть крайние случаи, которые не позволяют этого, но для его использования это должно быть легко реализовано. Я оставлю это на этом, так как мое второе опубликованное решение работает с моей стороны довольно хорошо. - person vividpk21; 21.08.2018
comment
@SpencerReschke, если решение работает для вас, я был бы признателен, если бы вы отметили его как ответ, если вам нужна дополнительная помощь, дайте мне знать. - person vividpk21; 21.08.2018
comment
@ vividpk21, похоже, на моем компьютере все работало нормально. У меня не будет доступа к компьютеру, на котором я внесу изменения до завтра. Если это сработает, я отмечу это как ответ. Спасибо за вашу помощь! - person Spencer Reschke; 21.08.2018
comment
@ vivdpk21 В итоге я проверил цвета пикселей, и это сработало отлично. Второе решение, которое вы предложили, используя количество дескрипторов, оказалось слишком непредсказуемым, чтобы его можно было использовать в реализации. В очередной раз благодарим за помощь. - person Spencer Reschke; 24.08.2018

РЕДАКТИРОВАТЬ: я чувствую, что это проблема XY (http://xyproblem.info/), где автор запускает файл Проводник и выбор файлов Hapfacs с помощью клавиатуры, потому что они не знают, как использовать аргументы командной строки, «для каждого файла запускать Hapfacs.exe $file».


Может быть, вам следует вызывать Hapfacs через Python, а не пытаться автоматизировать проводник?

Встроенный subprocess.Popen является гибким для трубопроводов.

subprocess.call и библиотеку plumbum проще использовать, если вы хотите вызвать программу и дождаться ее завершения.

person nyanpasu64    schedule 21.08.2018
comment
Вызов программы и ожидание ее завершения здесь бесполезны, потому что explorer.exe немедленно завершает работу после того, как сообщит реальному процессу Explorer открыть новое окно, что является всей проблемой, которую пытается решить OP, а не то, что хотел OP в любом случае, даже если бы это было не так, потому что им нужно взаимодействовать с окном, прежде чем оно закроется. - person abarnert; 21.08.2018
comment
Я чувствую, что это проблема XY, когда автор запускает File Explorer и выбирает файлы Hapfacs с помощью клавиатуры, потому что они не знают, как двойной щелчок по файлу на самом деле запускает webbrowser.open(file) или Hapfacs.exe $file, что можно сделать напрямую через Python. - person nyanpasu64; 21.08.2018