1 (изменено: mih, 2011-09-26 16:00:44)

Тема: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Есть процесс, не имеющий окна, а имеющий только значок в трее (через него можно увидеть и пункт "Выход"), нужно завершить этот процесс непринудительно.
"WinClose", нормально закрывает процесс с окном: пробовал использовать WinTitle в форме ahk_pid pid_процесса — результата не даёт (если применить это на процессах, имеющих окно, работает нормально);
"Process, close, имя_процесса" — принудительно убивает процесс, к тому же после этого остаётся иконка — придётся обновлять трей.

Как нормально м без эмуляции кликов по трею завершить такой процесс? Спасибо.

2

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

mih, префикс в названии темы.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

3

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Может быть, приложению нужно передать какое-то сообщение?

4 (изменено: mih, 2011-09-22 10:57:57)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Я ещё до того, как писать, подумал: "Может быть, приложению нужно передать какое-то сообщение?". А потом подумал так: Windows, когда штатно уходит в перезагрузку, закрывает все программы независимо от наличия у них окон — и все параметры этих программ без проблем сохраняются. Значит, существует стандартное сообщение для нормального закрытия любого, даже безоконного, приложения (а не для их окна, как делает "WinClose"; действие которого аналогично Alt_F4 главному окну, как я понимаю; и может привести, например, к сворачиванию окна в трей).

Что же нужно послать процессу для его штатного закрытия?

5

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

А ты уверен, что приложение действительно не имеет окон, даже скрытых? Ты проверял это?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6 (изменено: mih, 2011-09-23 03:09:27)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Приложение, в связи с которым возник этот вопрос —  не имеет никаких окон, даже скрытых.
А то, которое я позже приводил в пример — что оно вместо закрытия сворачивается по Alt_F4 в трей — то да, имеет скрытые окна; т.к. я сам в настройках указываю: сворачиваться в трей по крестику. И после этого никакие крестики, Alt_F4 и WinClose не могут закрыть это приложение — оно сворачивается в трей, а окна становятся скрытыми. Получается, что обычными средствами AHK я не могу нормально закрыть это приложение.
Дальше: в меню трейного значка имеется пункт "Выход", по которому происходит не только выход, но и сохранение некоторых изменений, сделанных в процессе работы с этим приложением; причём они действительно сохраняются именно в этот момент; если же просто убить это приложение — эти изменения не сохраняются.
И в то же время я знаю: если я буду перезагружать систему, то те самые изменения будут сохранены. То есть система умеет нормально его закрыть, а я с помощью AHK — нет. Но система же не читает меню: "где это там у него "выход", щас нажму!", — значит есть стандартный способ. Какой?

7

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

А разве taskkill без ключа /f завершает процессы не «нормально»?

8 (изменено: mih, 2011-09-23 18:59:05)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Проверил.

teadrinker был прав, а я поторопился, виноват. То приложение, которое имеет только значок в трее, — действительно имело единственное скрытое окно. И при закрытии его оно закрывается вместе со своим значком (надо указать DetectHiddenWindows On).  Команда  taskkill  действует на него точно так же. Это вроде похоже на нормальный выход (но т. к. приложение не имеет параметров, которые сохраняются через выход, не знаю, как удостовериться).

А у handycache (теперь я уже с ним борюсь, из принципа) очень много таких окон (134 штуки). И вот интересно: применение taskkill (с ключом  /pid или  /IM - неважно, но без  /F) в случае, если существует  явное окно  handycache — закрывает процесс "нормально" сразу. А если handycache свёрнуто в трей (это происходит по обычной команде "Свернуть", т.е. кнопка "_"), то taskkill закрывает все его окна ПОШТУЧНО: каждый раз их становится на одно меньше, причём если у handycache НЕ стоит галка "сворачивать в трей вместо закрытия"  — то его процесс все-же в какой-то момент закрывается ("нормально") — но повторю, команду надо выполнить много раз.

Если же у handycache поставлена галка "сворачивать в трей вместо закрытия", то при многократном повторении  taskkill количество окон уменьшается до 111, далее taskkill становится бессилен (но несмотря на это, пишет: "Процесс, с идентификатором 666, успешно завершен") — и процесс никогда не закрывается.

В AHK: "WinClose" закрывает "нормально" процесс  handycache; а если указать "DetectHiddenWindows On" — то закроет и свёрнутое в трей (тут уточнение: по имени процесса — сразу, а по ahk_pid надо циклить, пока не переберёт все окна), но опять же: если НЕ стоит галка "сворачивать в трей вместо закрытия".

То есть: разница между "WinClose" и taskkill у меня получилась в том, что в случае, если есть только скрытые окна — "WinClose" хоть не надо циклить (если использовать имя процесса), —  а второе работает только перебором (это именно для "нормального" закрытия, без ключа /F).

Если же галка "сворачивать в трей вместо закрытия" поставлена — handycache вообще закрыть нормально ничем не удаётся.

Вот что выяснилось, и пока способа "нормально" закрыть приложение, находящееся в режиме "сворачивать в трей вместо закрытия" — я пока не нашёл. Система же, не спотыкаясь, — закрывает его с сохранением параметров при уходе в перезагрузку.

9 (изменено: Александр_, 2011-09-26 01:49:14)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

mih пишет:

Вот что выяснилось, и пока способа "нормально" закрыть приложение, находящееся в режиме "сворачивать в трей вместо закрытия" — я пока не нашёл. Система же, не спотыкаясь, — закрывает его с сохранением параметров при уходе в перезагрузку.

При завершении сеанса всем приложениям отправляется сообщение WM_QUERYENDSESSION- отправьте его вашему пациенту.

10 (изменено: mih, 2011-09-26 05:28:01)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Оно бессильно даже против Блокнота; проверьте, пожалуйста:

SetTitleMatchMode, 2
DetectHiddenWindows On
PostMessage, 0x11, ,0x00000001,, Безымянный

lParam пробовал 0, 1, 0x40000000, 0x80000000; смотрел тут.

Заодно спрошу: на форуме несколько раз (пример) встречалась непонятная запись типа:
PostMessage,WM_QUERYENDSESSION:=0x11,,,   — зачем там присваивание?

11

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Если у приложения есть окно, для выхода достаточно послать ему WM_QUIT:

PostMessage, 0x12,,,, Безымянный   ; WM_QUIT = 0x12
mih пишет:

зачем там присваивание

Чтобы сразу показать, что имеется в виду под цифрами 0x11, и в дальнейшем использовать просто WM_QUERYENDSESSION.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

mih пишет:

Оно бессильно даже против Блокнота;

блокнот не обрабатывает сообщения WM_QUERYENDSESSION/WM_ENDSESSION.
WM_QUERYENDSESSION- говорит приложению, что начался процесс выхода из системы.
WM_ENDSESSION- что система вот-вот вырубится и приложение уже не получит сообщения WM_QUIT от системы. Если приложение долго не заканчивает обработку этого сообщения, то пользователь видит табличку "эти программы не отвечают, убить их?".

13

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Александр_, а как тогда закрывается Блокнот при завершении сеанса? Или он не реагирует только на эти сообщения посланные лично ему, а те же, но широковещательные — обрабатывает?

14 (изменено: mih, 2011-09-26 17:36:16)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Про Блокнот — я имел в виду, что, конечно, — сначала проверил на handycache (в режимах: с окнами, со скрытыми окнами, и "сворачивать в трей вместо закрытия") WM_QUERYENDSESSION и WM_ENDSESSION (0x16), никакого эффекта (точнее, handycache как-то хитро ломается, но не закрывается  — это точно). Вообще, этими сообщениями мне не удалось закрыть ни одного приложения. Посылал их и через InqSoft Window Scanner — эффект нулевой. Можно примерчик результативного применения этих сообщений (или хоть табличку увидеть: "Убить их?")?

А сообщение WM_QUIT — у меня все процессы закрывает аварийно, значки в трее остаются (а handycache вдобавок выдаёт: "Division by zero!"). Вообще (я повторю): пусть handycache — программа мудрёная, но система его всё-же закрывает нормально (на нём это легко увидеть — у него настройки применяются сразу, но сохраняются на диск — при нормальном выходе).

15

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Вот так можно:

SendMessage, WM_QUERYENDSESSION := 0x11,, 1,, Безымянный
if ErrorLevel = 1
{
   SendMessage, WM_ENDSESSION := 0x16, 1,,, Безымянный
   Process, Close, notepad.exe
}
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

16

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

alexii пишет:

Александр_, а как тогда закрывается Блокнот при завершении сеанса? Или он не реагирует только на эти сообщения посланные лично ему, а те же, но широковещательные — обрабатывает?

Примерный механизм с оконными приложениями:
1) Приложению посылается сообщение WM_QUERYENDSESSION с кодом ENDSESSION_LOGOFF. Точнее всем потокам процесса, имеющим цикл выборки. Заведует процессом оповещения csrss.exe.
2.1) Приложение возвращает TRUE, подтвердив готовность завершить работу.
2.2) Приложение возвращает FALSE.
3.1) Приложению посылается сообщение WM_ENDSESSION с WPARAM=TRUE. Во время обработки этого сообщения все данные должны быть сохранены. Если приложение не завершится само, то будет убито системой без предупреждения. На размышление даётся HKEY_CURRENT_USER\Control Panel\Desktop\HungAppTimeout или 5000 миллисекунд(по крайней мере в XP так было).
3.2) Приложению посылается сообщение WM_ENDSESSION с WPARAM=FALSE. Выключения не будет, отбой тревоги .

mih пишет:

Можно примерчик результативного применения этих сообщений (или хоть табличку увидеть: "Убить их?")?

DetectHiddenWindows, On 
WM_QUERYENDSESSION:=0x11
WM_ENDSESSION     :=0x16
ENDSESSION_LOGOFF :=0x80000000

hWnd:=DllCall("FindWindowA","str","имя класса","str","заголовок окна")
WinGet pid, pid, ahk_id %hWnd%
SendMessage WM_QUERYENDSESSION, 0, ENDSESSION_LOGOFF, , ahk_id %hWnd%
if ErrorLevel
{
   SendMessage WM_ENDSESSION, 1, ENDSESSION_LOGOFF, , ahk_id %hWnd%
   hproc:=DllCall("OpenProcess", "int", 0x0001,"int" , 0, "int", pid)
   DllCall("TerminateProcess", "int", hproc, "int", -1)
}
else
{
   SendMessage WM_ENDSESSION, 0, ENDSESSION_LOGOFF, , ahk_id %hWnd%
   MsgBox приложение послало нас ...
}
mih пишет:

(точнее, handycache как-то хитро ломается, но не закрывается  — это точно)

скорее всего:
1) Во время ломания все данные сохранились и приложение ждёт пока его убьют.
2) Не тому окну отправили сообщение.

17

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Не правильно

if ErrorLevel

т. к. если приложение не готово завершаться, ErrorLevel будет равен "FAIL", и условие выполнится всё равно.
Правильно, как в примере выше

if ErrorLevel = 1
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

18

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

teadrinker пишет:

Не правильно

if ErrorLevel

т. к. если приложение не готово завершаться, ErrorLevel будет равен "FAIL", и условие выполнится всё равно.
Правильно, как в примере выше

if ErrorLevel = 1

если приложение не готово завершится, то там будет ноль(FALSE). А "FAIL" говорит о том, что сообщение не было отправлено. по хорошему там нужно три варианта учитывать, но я в примере ошибки намерено не отлавливал, чтобы показать механизм.

19

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Не нужно цитировать предыдущий пост целиком.

Александр_ пишет:

если приложение не готово завершится, то там будет ноль(FALSE). А "FAIL" говорит о том, что сообщение не было отправлено. по хорошему там нужно три варианта учитывать

Во всяком случае, блокнот с несохранённым текстом выдаёт "FAIL". И зачем три, когда подходит только один?
И вместо

WinGet pid, pid, ahk_id %hWnd%
hproc:=DllCall("OpenProcess", "int", 0x0001,"int" , 0, "int", pid)
DllCall("TerminateProcess", "int", hproc, "int", -1)

проще

Process, Close, [Имя процесса]

ведь имя известно.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

20

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Во время ломания все данные сохранились и приложение ждёт пока его убьют.

А ведь точно, Александр_, точно!

21

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

teadrinker пишет:

Во всяком случае, блокнот с несохранённым текстом выдаёт "FAIL".

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

teadrinker пишет:

И зачем три, когда подходит только один?

Если приложение получает сообщение WM_QUERYENDSESSION, то оно должно получить и WM_ENDSESSION. Например для прокси-сервера вполне логично такое поведение: при получении WM_QUERYENDSESSION сохраняем настройки и перестаём устанавливать новые соединения, обрабатывая только уже имеющиеся. Теперь если не послать ему сообщение WM_ENDSESSION с отменой приказа о прекращении работы, то мы получим некорректно функционирующую программу.

22

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Наверно, тут ты прав.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

23 (изменено: mih, 2011-09-26 23:46:52)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Спасибо!!

24 (изменено: Sergij, 2013-02-14 18:34:15)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Хотел сделать простенький код для убивания - завершения любого приложения по горячей кнопке , для начала попробовал.


f4::
Process, Close, calc.exe
RunWait taskkill /im calc.exe
return

Не завершает

taskkill тоже не помогает, если вести команду в командной строке DOS отлично работает, если через AHK RunWait то выдает на секунду окно,
недостаточно памяти для завершения операции,  и ноль эффекта

Единственное что сработало это


Run, calc.exe, , , process_id
Sleep 1000
Process, Close, %process_id%

А вот это уже не в какую


Process, Exist, calc.exe
pid=%ErrorLevel%
Process, Close, %pid%

Может глюки в системе Windows 7 64bit

25 (изменено: Grey, 2013-02-15 06:54:07)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

А так работает?:

app:="calc.exe"
query:="SELECT Name FROM Win32_Process WHERE Name='"app "'"

F4::
   If (oWMI:=ComObjGet("winmgmts:").ExecQuery(query)).Count
      For colItem In oWMI
         colItem.Terminate
   Else MsgBox, 262144, % A_Space, % "Not found", 1
   KeyWait, % A_ThisHotkey
   oWMI:=colItem:=""
   Return

26

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Так тоже не работает выдает ошибку на строке №5

   If (oWMI:=ComObjGet("winmgmts:").ExecQuery(query)).Count

Пробовал так

PostMessage, 0x12,,,, Калькулятор   ; WM_QUIT = 0x12

Не работает

Попробовал сегодня на другом компе вышеприведенные примеры, вроде все работает,  Там Windows 7  32.

Также пробовал режим совместимости с Windows XP для AHK выставить, один раз сработал taskkill, больше не работал.
Пробовал скачивать AHK 64 бит AutoHotkey_Lw64.zip не помогает.

27

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Вроде нашел проблему, хотя не до конца все ясно.
У меня установлен Comodo Internet Security, я отключил всю его защиту и скрипт заработал, а после того как снова включил защиту, скрипт продолжает работать.
Возможно комодо уже принял AHK за своего. Как сразу не догадался
И даже ваш вариант (как наиболее мне непонятный ) тоже работает.
Спасибо

28 (изменено: stealzy, 2014-04-26 13:20:14)

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

По итогам обсуждения сделал код, эмулирующий сообщения системы процессу при выключении, предлагаю топикстартеру вынести в топ:

DetectHiddenWindows, On
windowID := WinExist("AHK_class Notepad") ; Окно вашего приложения

WinGet, procPID, PID, AHK_id %windowID%
SendMessage, WM_QUERYENDSESSION := 0x11,, 1,, AHK_id %windowID%
if ErrorLevel = 1
{
    PostMessage, WM_ENDSESSION := 0x16, 1,,, AHK_id %windowID%
    Sleep 5000
    Process, Close, %procPID%
} else {
    MsgBox, 4132, Внимание!, Приложение не отвечает`, закрыть его аварийно?, 5
    IfMsgBox Timeout
        PostMessage, WM_QUIT := 0x12,,,, AHK_id %windowID% ; или Process, Close, %procPID%
    IfMsgBox Yes
        PostMessage, WM_QUIT := 0x12,,,, AHK_id %windowID% ; или Process, Close, %procPID%
    Else
        SendMessage, WM_QUERYENDSESSION := 0x11,, 0,, AHK_id %windowID%
} 
; чистим Tray от оставшихся иконок, кому надо

Можно оформить в виде функции и радоваться.

0xFFFFFF
0xFF0000
0xFFFFFF

29

Re: AHK: Ищу надёжный способ "нормально" завершать любой процесс

Экспериментальным путем получился такой код:

;DetectHiddenWindows,On
SetTitleMatchMode,2



v:=CorrectCloseProcess("ahk_exe notepad.exe")
;v:=CorrectCloseProcess("Блокнот")
msgbox,% "Попыток закрытия: " v



CorrectCloseProcess(WinTitle)
{
  loop,50
  {
    a++
    t:=a_tickcount
    SendMessage,WM_QUERYENDSESSION:=0x11,0,1,,% WinTitle
    d:=a_tickcount-t
    if (d>100)
      return -1
    b:=ErrorLevel
    SendMessage,WM_CLOSE:=0x10,,,,% WinTitle
    if (b="FAIL")
      return a
    sleep,10
  }
}
Win 7 x64
AHK v1.1.33.02
                       Справка тебе в помощь.
+ DD