Скрипт не всегда срабатывает

Помощь в написании скриптов
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Скрипт не всегда срабатывает

27 Dec 2023, 07:00

Здравствуйте. Есть скрипт Autohotkey. Его задача - отслеживать, когда в определенном окне появляется и пропадает кнопка. Если кнопка в отслеживаемом окне исчезла - через 5 секунд он должен показывать Msgbox.
Проблема - скрипт работает, когда ему хочется. Msgbox показывается иногда(!), и то только когда окно активно и в нем выполняются какие-то действия. Если окно после отсчета времени свернуто или неактивно, скрипт не работает и не показывает Msgbox. Хотя он должен его развернуть и показать Msgbox. Как это исправить?
Окно, в котором скрипт должен отслеживать наличие/отсутствие кнопки. появляется не так часто, раз в 2-3 минуты, и кнопка в нем пропадает не сразу, т.е. у скрипта есть возможность отследить момент его появления и найти/не найти кнопку.

Code: Select all

#SingleInstance, force
#NoEnv

ProgramName := "Program1"

Loop
{
    WinWait, % "Диалоговая форма ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1",, 5 ; ждем появление окна
	if !ErrorLevel 
	{
	ControlGet, OutputVar, Visible,, WindowsForms10.Window.8.app.0.329445b_r8_ad184		; проверяем наличие кнопки в окне
		if (OutputVar) ; если кнопка в данном окне обнаружена
			Continue ;продолжаем проверку
		else				 ; если кнопки в данном окне не обнаружено
			{
			Sleep, 5000 ; ждем 5 секунд
			IfWinExist, % "Диалоговая форма ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1" ; если это окно все еще существует
				{
				IfWinNotActive, % "Диалоговая форма ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1" ; и оно неактивно
					{
					ControlGet, OutputVar, Visible,, WindowsForms10.Window.8.app.0.329445b_r8_ad184		; проверяем наличие кнопки в нем еще раз
					if (OutputVar)
						Continue
					else				 ; если кнопки в данном окне снова не обнаружено
						{
						WinActivate ; делаем окно активным
						MsgBox, 262160, % "Program1", % "Готово"	; и показываем MsgBox
						}
					}
					Else ; если это окно все еще существует, и оно активно
					MsgBox, 262160, % "Program1", % "Готово"	; показываем MsgBox
				}
				Else ; если окно не существует, продолжаем проверку
				Continue
			}
	}
	else
	Continue ; если окно не появилось, начинаем проверку сначала
}
vmech
Posts: 356
Joined: 25 Aug 2019, 13:03

Re: Скрипт не всегда срабатывает

27 Dec 2023, 08:41

Code: Select all

#Requires Autohotkey v1.1
#SingleInstance, force
#NoEnv

ProgramName	:= "Program1"
TitleName	:= "Диалоговая форма"
TitleClass	:= "ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1"
WindowTitle	:= TitleName . A_Space . TitleClass
ButtonName	:= "WindowsForms10.Window.8.app.0.329445b_r8_ad184"
CtrlCommand	:= "Visible"

Loop
{
	Sleep, 1000
	WinWait, % WindowTitle
	if !ErrorLevel 
	{
		while WinExist( WindowTitle )
		{
			if !WinActive( WindowTitle )
				WinActivate, % WindowTitle
			ControlGet, OutputVar, % CtrlCommand,, % ButtonName, % WindowTitle
			if !OutputVar
			{
				MsgBox, 262160, % ProgramName, % "Готово"
				break
			}
			Sleep, 1000
		}
	}
}

!+x::ExitApp	; {Alt}{Shift}{X}
Please post your script code inside [code] ... [/code] block. Thank you.
marusa122
Posts: 135
Joined: 22 Mar 2023, 07:48

Re: Скрипт не всегда срабатывает

29 Dec 2023, 04:45

@vmech, со скриптом была проблема - окно, которое нужно отслеживать при появлении, постоянно становится активным, невозможно работать с другими окнами. Нужно, чтобы оно становилось активным один раз - после отсчета времени. и после этого показывался Msgbox.
Пробовала перенести WinActivate перед Msgbox - тогда скрипт работает нормально. Но если окно после отсчета времени будет не просто неактивно, а свернуто - скрипт на него перестает реагировать и не показывает Msgbox (хотя после отсчета времени должен развернуть это окно и показать Msgbox). Как это исправить?

Code: Select all

#Requires Autohotkey v1.1
#SingleInstance, force
#NoEnv

ProgramName	:= "Program1"
TitleName	:= "Диалоговая форма"
TitleClass	:= "ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1"
WindowTitle	:= TitleName . A_Space . TitleClass
ButtonName	:= "WindowsForms10.Window.8.app.0.329445b_r8_ad184"
CtrlCommand	:= "Visible"

Loop
{
	Sleep, 1000
	WinWait, % WindowTitle
	if !ErrorLevel 
	{
		while WinExist( WindowTitle )
		{
			ControlGet, OutputVar, % CtrlCommand,, % ButtonName, % WindowTitle
			if !OutputVar
			{
				Sleep, 5000
			if !WinActive( WindowTitle )
				WinActivate, % WindowTitle
				; WinRestore, % WindowTitle - пробовала добавить и перед, и после, и вместо WinActivate, не помогло
				Sleep, 500
				MsgBox, 262160, % ProgramName, % "Готово"
				continue
			}
			Sleep, 1000
		}
	}
}

!+x::ExitApp	; {Alt}{Shift}{X}
vmech
Posts: 356
Joined: 25 Aug 2019, 13:03

Re: Скрипт не всегда срабатывает

29 Dec 2023, 09:17

@marusa122
Потому что ты сделала результат работы ControlGet условием для работы всего остального кода.
Если окно свёрнуто, или неактивно, тогда соответственно ControlGet НЕ обнаруживает кнопку - условие НЕ выполняется, и ВЕСЬ код внутри скобок if !OutputVar НЕ работает.
И не будет работать. Пока окно не будет развёрнуто/активировано руками.

Смысл моего кода был в том, что окно СНАЧАЛА делается активным, а уже ЗАТЕМ в активном окне ищется кнопка.
Одна только эта затея уже дурацкая сама по себе - у меня тоже окно другой программы бесконечно мелькало, и не давало пользоваться другими окнами.
marusa122 wrote:
29 Dec 2023, 04:45
Как это исправить?
Я не знаю. Какой то дурацкий алгоритм. Его условия - взаимоисключающие.
Я не понимаю как работает окно в твоей программе. Мне затруднительно что то предпринимать не имея доступа к этому окну. Только так можно попытаться понять логику его работы.

Пока что я вижу только такое решение:
Раз попытка имплементации автоматической активации окна провалилась - избавимся от неё совсем.
Тебе придётся руками разворачивать свёрнутое окно - по другому (пока что) никак.
В скрипте оставим проверку и 1. наличия окна, и 2. его активности.
И только после выполнения обоих условий скрипт будет проверять наличие КНОПКИ в окне.
Других вариантов я пока не вижу.

Code: Select all

#Requires Autohotkey v1.1
#SingleInstance, force
#NoEnv

ProgramName	:= "Program1"
TitleName	:= "Диалоговая форма"
TitleClass	:= "ahk_class WindowsForms10.Window.8.app.0.329445b_r8_ad1"
WindowTitle	:= TitleName . A_Space . TitleClass
ButtonName	:= "WindowsForms10.Window.8.app.0.329445b_r8_ad184"
CtrlCommand	:= "Visible"

Loop
{
	Sleep, 1000
	WinWait, % WindowTitle
	if !ErrorLevel 
	{
		while WinExist( WindowTitle )
		{
			if WinActive( WindowTitle )
			{
				;;; WinActivate, % WindowTitle
				ControlGet, OutputVar, % CtrlCommand,, % ButtonName, % WindowTitle
				if !(OutputVar)
				{
					MsgBox, 262160, % ProgramName, % "Готово"
					break
				}
				Sleep, 1000
			}
		}
	}
}

!+x::ExitApp	; {Alt}{Shift}{X}
ЗЫ. По хорошему, условие if !ErrorLevel в этом коде вообще ЛИШНЕЕ.
Потому что WinWait без таймаута и так будет ждать окно до бесконечности.
И только когда окно, подходящее по условию проверки, «материализуется», только тогда код ниже будет выполнен.
А технически, внутри WinWait, в цикле выполняется та же самая проверка if WinExist().
Просто это делает скомпилированный машинный код самого Autohotkey, оптимизированный для работы с операционной системой.
Please post your script code inside [code] ... [/code] block. Thank you.

Return to “Помощь”

Who is online

Users browsing this forum: No registered users and 92 guests