Что нового

[Элементы GUI] Как создать цикл сворачивание и разворачивание окна интересующего приложения

alex_tm

Новичок
Сообщения
16
Репутация
0
Ситуация такая:
Есть программа, которая при завершении всех действий с ней, не высвобождает используемую память, и при последующем продолжении работы в ней, ещё больше под себя резервирует, что в итоге делает её ужасно прожорливой. Было замечено, что обычная процедура - свернуть-развернуть окно - делает необходимое высвобождение памяти, и снижает объём используемой памяти с 400 Мб до 40 Мб. Нужен скрипт, который делает процедуру "свернуть-развернуть окно" через заданный промежуток времени, а так же прекращал свою работу после закрытия окна той программы.
Пролистав справку, у меня почти получился нужный скрипт, но он делает Exit по истечении значения sleep, а это не устраивает - нужно чтобы Exit срабатывал сразу, как закроется программа.

На примере Блокнота - скрипт должен запустить программу notepad.exe и каждые 20 секунд должен делать ему "свернуть-развернуть". При этом, если закрыть notepad.exe - скрипт должен завершить свою работу. В моём примере завершение работы скрипта происходит по истечении времени, указаному в sleep (20 секунд), а это не устраивает, т.к. это значение может быть и 30 минут и 60 минут. Так долго ждать завершения работы скрипта - не устраивает!

Помогите оптимизировать! Спасибо!

Код:
Run("Notepad.exe", "", @SW_MAXIMIZE)
while 1
WinSetState("Безымянный", "", @SW_MINIMIZE)
WinSetState("Безымянный", "", @SW_MAXIMIZE)
WinActivate("Безымянный", "")
Sleep(20000)
If ProcessExists("notepad.exe") = 0 Then Exit
wend
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Код:
AdlibRegister('CheckApp', 1000)
$mytime = 60*60*1000; 1 hour
Run("Notepad.exe", "", @SW_MAXIMIZE)
while 1
WinSetState("Безымянный", "", @SW_MINIMIZE)
WinSetState("Безымянный", "", @SW_MAXIMIZE)
WinActivate("Безымянный", "")
Sleep($mytime)
wend

Func CheckApp()
    If Not ProcessExists("notepad.exe") Then Exit
EndFunc



Добавлено:
Сообщение автоматически объединено:

версия без Adlib
Код:
$mytime = 60*60*1000; 1 hour
Run("Notepad.exe", "", @SW_MAXIMIZE)
$start = TimerInit()
While 1
    If TimerDiff($start) > $mytime
        WinSetState("Безымянный", "", @SW_MINIMIZE)
        WinSetState("Безымянный", "", @SW_MAXIMIZE)
        WinActivate("Безымянный", "")
        $start = TimerInit()
    EndIf
    If Not ProcessExists('notepad.exe') Then ExitLoop
    Sleep(100)
Wend
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
Kaster Спасибо огромное за помощь - всё действительно работает. Проверил на локальном компьютере - всё ОК.
К сожалению, у меня появилась проблема с другой программой, к которой нужно применить такое же действие скрипта.
Дело касается запуска программы 1С:Предприятие (1cv8.exe) в терминальном режиме на сервере. По ходу проверки работы скрипта выяснилось, что скрипт не завершает свою работу после завершения работы процесса 1cv8.exe. И как мне кажется по той причине, что в списке процессов висят ещё несколько копий этого же процесса, запущенного от имени других пользователей.
У меня появилась подозрение, что в качестве условия для EXIT нужно брать не отсутствие в списке процессов файла 1cv8.exe, а закрытие окна с определённым заголовком.
Я попытался реализовать это дополнительной проверкой присутствия такого окна:
Код:
Func CheckApp()
	If Not ProcessExists("1cv8.exe") Then Exit
    	If Not WinExists("1С:Предприятие") Then Exit
EndFunc

Но это оказалось сложнее, чем я думал. И всё из за того, что запуск 1С сопровождается появлением 3-х разных окон с разными заголовками:
1-е окно с заголовком "Запуск 1С:Предприятия" - где выбирается нужная база и нажимается кнопка "Подключиться"
2-е окно с заголовком "1С:Предприятие. Доступ к информационной базе" - где указывается имя пользователя и пароль.
3-е окно - это сама программа 1С с заголовком "1С:Предприятие"
Я внёс проверку всех трёх условий таким образом:
Код:
Func CheckApp()
	If Not ProcessExists("1cv8.exe") Then Exit
    If Not WinExists("Запуск 1С:Предприятия") Then Exit
	If Not WinExists("1С:Предприятие. Доступ к информационной базе") Then Exit
	If Not WinExists("1С:Предприятие") Then Exit
EndFunc
, но уже и так стало понятно, что после запуска сразу же срабатывают условия для EXIT, так как вышеуказанные окна ещё не появлялись.
Помогите реализовать правильное выполнение этих условий! Спасибо!
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
alex_tm
мне, чесгря, сложно представить, как окно может существовать без процесса. ибо это невозможно. окно есть пока есть процесс. стало быть ты просто мониторишь не тот, который нужен. вылови настоящий и проверяй его. если же работа программы сопровождается несколькими процессами, то проверяй каждую и только по завершению всех (ну или какого нибудь самого главного, завершение которого точно дает сигнал о завершении скрипта) делай Exit/ExitLoop
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
В терминальном режиме - в списке процессов может быть большое множество копий одного и того же файла, запущенного от имени разных пользователей. Насколько я понял - скрипт потому и не завершает свою работу после закрытия мною моей копии программы 1С, т.к. в списке процессов висят ещё 15 таких же файлов с таким же названием.
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
Попробую сформулировать вопрос иначе - как реализовать проверку так, чтобы проверялись все три условия и выполнение хотя бы одного из них продолжало бы цикличную работу скрипта?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Высвободить память сворачиванием-разворачиванием окна невозможно. Память может освободить только сама программа, чудес не бывает. При сворачивании-разворачивании окна система (не программа) свопит всю память процесса, какую возможно. Аналогичные действия делает функция _WinAPI_EmptyWorkingSet() из WinAPEx. Я об этом уже писал.

http://autoit-script.ru/index.php?topic=1556.msg26562#msg26562
http://autoit-script.ru/index.php?topic=2531.msg18362#msg18362
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
Уважаемый Yashied. Я доверяю Вашему опыту, но должен вас огорчить. С программой 1С такие чудеса происходят. Я не могу настаивать на том, чтобы Вы лично проверили это у себя, но если бы была такая возможность - Вы бы сами убедились в этом. Условия для демонстрации этого явления не сложные - XP или Server 2003, и установленная на них 1С версии 8.х (8.0, 8.1, 8.2) с базовой конфигурацией. Запуск 1С (1cv8.exe) - после входа в программу - в диспетчере задач смотрим на размер используемой памяти процессом 1cv8.exe - он составляет около 60 МБ. Просто сворачиваем окно 1С - и размер занимаемой памяти тут же снижается до 4-х МБ. Если в процессе работы 1С делать разные подсчёты, делать отчёты, и т.п. - размер используемой памяти постоянно увеличивается - доходит до 500 МБ. Даже если прекратить проведение расчётов и закрыть их, но при этом не закрывать само окно программы - размер занимаемой процессом памяти не уменьшается. Только завершение работы с программой освобождает занимаемый объём. Но мною и моими коллегами случайно была замечена такая особенность - если периодически в программе 1С делать "свернуть-развернуть" - становится возможным уменьшение занимаемой памяти. А теперь представьте как дело обстоит на терминальном сервере, где одновременно работают 20-25 пользователей, и у каждого запущена своя копия программы 1С? В среднем около 6 ГБ оперативной памяти выделяется сугубо на нужды одной программы. Но ведь есть же и другие одновременно запущенные процессы, без которых не обходится обычная работа на сервере?!
Я осознаю, что это ситуация - специфична, и вину за подобное явление можно возложить на авторов 1С. Как вариант - можно поговорить с каждым пользователем и попросить их не забывать каждые пол-часа или каждый час делать "свернуть-развернуть". Но расчитывать на то, что они будут это делать с должной периодичностью - не приходится. И их можно понять - забыли, заработались.
Поэтому использование вышеуказанного скрипта выглядит более чем спасительным и решило бы всю проблему сразу.
На просторах интернета давно обсуждается вопрос связанный с таким интересным поведением программы 1С, но производителями до сих пор это явление не исправлено.
Одна надежда на возможности работы AutoIt.
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
alex_tm
Хм... а есть возможность каждому закинуть в автозапуск по скрипту AutoIt?
Можно сделать, чтобы скрипт будет отслеживал простой мыши и клавиатуры и если нет пользователя >5 минут запускался скрипт. Все люди отходят за чаем/кофе/обедать/туалет... ещё куда либо... :smile: Проблем с забываем и напоминанием не будет... :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
alex_tm

Ты меня не понял. Я тебе фактически порекомендовал использовать функцию _WinAPI_EmptyWorkingSet() вместо сворачивания-разворачивания. Попробуй.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
alex_tm,
Попробуйте так:
Код:
#include <WinAPIEx.au3>

Opt('MustDeclareVars', 1)

Global $iMax = 75 * 1024 * 1024 ; 75 Mb макс допустимый объем потребляемой памяти
Global $iWait = 10 * 1000 * 60 ;10 min проверка каждые 10 минут
Global $sProcess = 'notepad.exe';процесс, за которым следим.

HotKeySet('{Esc}', '_Exit');Esc - выход
AdlibRegister('_My_Func', $iWait)
While 1
	Sleep(500)
WEnd

Func _My_Func()
	Local $aList = ProcessList($sProcess)
	If Not $aList[0][0] Then Return
	For $i = 1 To $aList[0][0]
		Local $aMem = ProcessGetStats($aList[$i][1])
		If $aMem <> 0 Then
			If $aMem[0] > $iMax Then
				ConsoleWrite('PID: ' & $aList[$i][1] & ' - ' & Round($aMem[0] / (1024 * 1024), 2) & ' Mb' & @CR)
				_WinAPI_EmptyWorkingSet($aList[$i][1])
			EndIf
		EndIf
	Next
EndFunc   ;==>_My_Func

Func _Exit()
	Exit
EndFunc   ;==>_Exit


WinAPIEx.au3
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
:laugh: Протестил с прожорливым FireFox... работает шикарно! :thumbs_up:
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
zlo-kazan

Будьте добры - поясните мне несмышлённому - что вы видоизменили в вышеуказанном скрипте под firefox?! - всего лишь firefox.exe вместо notepad.exe ?
И как вы увидели разницу? помогите разобраться! Я уже закипаю!
 

zlo-kazan

Скриптер
Сообщения
374
Репутация
100
С этой записью в одно мгновение FireFox стал потреблять ~10Mb. и потом снова набрал ~100+Mb
Код:
Global $iMax = 256 * 1024 * 1024 ; 75 Mb макс допустимый объем потребляемой памяти
Global $iWait = 10 ;10 min проверка каждые 10 минут
Global $sProcess = 'firefox.exe';процесс, за которым следим.

А с этой переход был 1 раз с ~400Mb до ~385Mb...
Код:
Global $iWait = 10 * 1000 * 60 ;10 min проверка каждые 10 минут
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
zlo-kazan
madmasles


Всё работает как надо!
Только хочу ещё уточнить - Global $iWait = 10 * 1000 * 60 ;10 min проверка каждые 10 минут - начинают отсчитываться с начала запуска скрипта, или с момента бездействия?
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
alex_tm
Прошло 10 минут (или сколько Вы поставите) с момента запуска скрипта - проверка, еще 10 - следующая, и т.д. По кнопке Esc - выход. Максимальный допустимый объем памяти тоже можете изменить на нужный Вам.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
OffTopic:
Вот так всегда, даешь идею, а все лавры достаются другим.

:smile:
 
Автор
A

alex_tm

Новичок
Сообщения
16
Репутация
0
А вот и нет, уважаемый Yashied. Я про Вас не забыл. Просто, немного увлёкся реализацией вашей идеи, и только недавно закончил опробывание!
Громаднейшее СПАСИБО Вам за ваши советы и подсказки! Дай Бог Вам здоровья! :thanks:

З.Ы. Кстати, писатели 1С до сих пор не решили вопрос с перерасходом памяти процессом, хотя этот вопрос остаётся открытым уже долгое время. К тому же, их детище - недешевое удовольствие, что, к сожалению, никак не сказывается на скорости исправления найденных проблем.
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Я еще хочу вас предостеречь от преждевременной радости. Что _WinAPI_EmptyWorkingSet(), что сворачивание-разворачивание, делают одно и тоже - свопят (не освобождают) память процесса. Когда снова будет обращение к этим данным, они будут восстановлены из свопа, что, естественно, потребует какого-то времени (небольшого, но возможно заметного). Поэтому я рекомендую вызывать эту функцию не просто через каждые 10 минут, а при условии, что данный процесс находится какое-то время в бездействии. Я это где-то уже писал на форуме и даже приводил формулу для вычисления загрузки процесса. "Загрузка процесса...".
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
alex_tm сказал(а):
Кстати, писатели 1С до сих пор не решили вопрос с перерасходом памяти процессом, хотя этот вопрос остаётся открытым уже долгое время. К тому же, их детище - недешевое удовольствие, что, к сожалению, никак не сказывается на скорости исправления найденных проблем.

А им это и не нужно. Главная цель 1С - содрать с вас побольше денег за ежемесячные обновления и новые версии программы. Потому, как конкурентов у них практически нет.
 
Верх