Что нового

[Процессы] Команда выхода из программы (не taskkill)

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
Интересует возможно ли послать программе/процессу команду выхода?

ПС. Убийство процесса очень сильно не подходит.
К примеру при завершении Windows программы выходят, а не убиваются процессы. Для этого нужно использовать WinApi или есть что-либо попроще?
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
http://autoit-script.ru/index.php?topic=22441.msg131124#msg131124

а чем системный инструмент taskkill не нравится?
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
joiner [?]
а чем системный инструмент taskkill не нравится?
Потому что после taskkill (и вообще какое-либо убийство процесса) у программы не запоминаются сохранения/позиции окна/и т.д.
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
у программы не запоминаются сохранения/позиции окна/и т.д.
Значит это GUI-приложение и достаточно закрыть его главное окно
Код:
WinClose()
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
InnI [?]
начит это GUI-приложение и достаточно закрыть его главное окно
Не, такое совсем не катит, потому что у меня много приложений, которые при таком действии сворачиваются в трей.
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
при таком действии сворачиваются в трей
Значит нужно использовать для выхода средства самого приложения - пункт главного меню или меню трея или что там у приложения предусмотрено.
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
InnI [?]
Значит нужно использовать для выхода средства самого приложения
Вот к этому и создал тему. То бишь нельзя методами Windows, так как она это делает при завершении или перезагрузке?

ПС. Потому как через меню трея это очень неудобно.
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
БлагоѨръ [?]
у программы не запоминаются сохранения/позиции окна/и т.д.
запоминает. потому и написал.
taskkill /pid 1234
без флага "принудительно"
завершил главный процесс хрома. запустил хром, окно появилось в тех же координатах и с теми же размерами. при этом хром не выводил сообщение, что можно восстановить вкладки, как это бывает при принудительном завершении.


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

либо так
Код:
#include <WinAPI.au3>
 #include <WindowsConstants.au3>
_WinAPI_PostMessage($hWnd,$WM_CLOSE,0,0)
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
joiner [?]
запоминает. потому и написал.
Да, немного не так описал. Оно запоминает те положения и прочее, которое было перед запуском той, или иной программы. К примеру я запустил Total Commander и открыл диск D, потом закрыл его, опять открыл и перешёл на диск E и воспользовался убийством процесса. И вот в таком случае, оно откроет его не на диске E, а на диске D.

ПС. И так по аналогии с большинством программ.
В случае с Chrome-ом - запустил, у меня там открыто 8 вкладок, закрываю 4 из них, убиваю процесс, запускаю снова - Chrome, там открыта одна вкладка с белой страницей, говорит, что он был завершён некорректно и отображает всплывающую подсказку и с восстановлением, нажимаю "Восстановить" и восстанавливаются не 4 вкладки, а 8.
И такой "гемморой" с подавляющий большинством программ. По этом причине и создал тему.

Что делает _WinAPI_PostMessage прочитал, а что делают переменные? Убивают или завершают?
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
как она это делает при завершении или перезагрузке
Код:
#RequireAdmin

#include <SendMessage.au3>
#include <WindowsConstants.au3>

$hWnd = WinGetHandle("Title")
$PID = WinGetProcess($hWnd)
If _SendMessage($hWnd, $WM_QUERYENDSESSION) Then
  _SendMessage($hWnd, $WM_ENDSESSION, True)
  If Not ProcessWaitClose($PID, 3) Then
    _SendMessage($hWnd, $WM_CLOSE)
    If Not ProcessWaitClose($PID, 3) Then
      _SendMessage($hWnd, $WM_DESTROY)
      If Not ProcessWaitClose($PID, 3) Then
        ProcessClose($PID)
      EndIf
    EndIf
  EndIf
Else
  MsgBox(0, "", "Приложение отказалось завершаться")
EndIf


Перехват и блокировка завершения работы Windows
 

joiner

Модератор
Локальный модератор
Сообщения
3,557
Репутация
628
БлагоѨръ [?]
Что делает _WinAPI_PostMessage прочитал, а что делают переменные? Убивают или завершают?
отправляет сообщение приложение, что оно должно завершиться
если завершение приложения подразумевает сохранение данных, то будет выведено сообщение. так что, однозначно просто не завершить приложение


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

БлагоѨръ [?]
В случае с Chrome-ом - запустил, у меня там открыто 8 вкладок, закрываю 4 из них, убиваю процесс, запускаю снова - Chrome, там открыта одна вкладка с белой страницей, го
завершать нужно основной процесс. в случае с хромом, в диспетчере задач он записан первым
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
joiner [?]
то будет выведено сообщение. так что, однозначно просто не завершить приложение
Ну это хорошо. Если редактирую чего-то в к примеру в Sublime.
завершать нужно основной процесс. в случае с хромом, в диспетчере задач он записан первым
У меня портативный и пользуюсь я Process Hacker-ом, убил через "Terminate Tree" (то бишь завершить дерево) на процессе ChromePortable.exe


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

InnI [?]

А как-бы этот код сделать для множества процессов?

ПС. Сейчас у меня к примеру в цикле, вот так
Код:
Global $aSvcNames[] = ['AdobeARMservice','Adguard Service','AGSService','GsServer','PSI_SVC_2', 'SbieSvc', 'SQLWriter', 'VMnetDHCP', 'VMware NAT Service', 'VMAuthdService', 'VMUSBArbService', 'WebDriveService','YandexBrowserService', 'Zoolz 2 Service', '{0CBD4F48-3751-475D-BE88-4F271385B672}']

Global $aProcNames[] = ['Adguard.exe', 'AdobeARM.exe','DefenderDaemon.exe','DTShellHlp.exe','elements64.exe','Ext2Mgr.exe','SbieCtrl.exe', 'SynTPEnh.exe', 'SynTPHelper.exe', 'TrueImageMonitor.exe','TibMounterMonitor.exe','vmware-tray.exe']

For $Name In $aSvcNames
  _Service_Stop($Name)
  Sleep(300)
Next

For $Name In $aProcNames
  ProcessClose($Name)
Next

Func _Service_Start($sService, $Computer = ".")
  ConsoleWrite($sService & @CRLF)
  Local $objWMI = ObjGet("winmgmts:\\" & $Computer & "\root\cimv2")
  If Not(IsObj($objWMI)) Then Return SetError(-2)
  Local $strQuery = "Select * from Win32_Service Where State = 'Stopped' And " & _
      "Name Like '"& $sService & "'"
  Local $colItems = $objWMI.ExecQuery($strQuery)
  If Not(IsObj($colItems)) Then Return SetError(-2)

  For $objItem in $colItems
    Return $objItem.StartService($objItem.Name)
  Next
  Return SetError(-1)
EndFunc   ;==> _Service_Start()

Func _Service_Stop($sService, $Computer = ".")
  ConsoleWrite($sService & @CRLF)
  Local $objWMI = ObjGet("winmgmts:\\" & $Computer & "\root\cimv2")
  If Not(IsObj($objWMI)) Then Return SetError(-2)
  Local $strQuery = "Select * from Win32_Service Where State = 'Running' And " & _
      "name like '"& $sService &"'"
  Local $colItems = $objWMI.ExecQuery($strQuery)
  If Not(IsObj($colItems)) Then Return SetError(-2)

  For $objItem In $colItems
    Return $objItem.StopService($objItem.Name)
  Next
  Return SetError(-1)
EndFunc  ;==> _Service_Stop()

БлагоДарю за ссылку.
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
этот код сделать для множества процессов
Оформите код в виде функции.
Для каждого элемента вашего массива процессов через _WinAPI_EnumProcessWindows определяете главное окно и передаёте его в функцию.
Или можно проще. Создайте массив заголовков окон и вызывайте функцию в цикле для каждого элемента массива.
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
InnI [?]
Или можно проще. Создайте массив заголовков окон и вызывайте функцию в цикле для каждого элемента массива.
БлагоДарю за помощь, буду пробовать.
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
joiner сказал(а):
http://autoit-script.ru/index.php?topic=22441.msg131124#msg131124
При таком варианте приложения завершаются так


joiner сказал(а):
либо так
Код:
#include <WinAPI.au3>
 #include <WindowsConstants.au3>
_WinAPI_PostMessage($hWnd,$WM_CLOSE,0,0)

Не пойму, как сделать.
Попробовал так
Код:
#Include <Array.au3>
 #include <WinAPI.au3>
 #include <WindowsConstants.au3>

If WinExists(@ScriptName) Then Exit
AutoItWinSetTitle(@ScriptName)

Global $title = _Process2Win('punto.exe')
_WinAPI_PostMessage($title,$WM_CLOSE,0,0)

Func _Process2Win($pid)
    if IsString($pid) then $pid = ProcessExists($pid)
    if $pid = 0 then return -1
    $list = WinList()
    for $i = 1 to $list[0][0]
        if $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) then
            $wpid = WinGetProcess($list[$i][0])
            if $wpid = $pid then return $list[$i][0]
        EndIf
    Next
    Return -1
EndFunc
Все приложения начали закрываться так, как мне нужно (делались запросы на сохранение; у тех, что нет чего сохранять сделали выход). Только я указал конкретный процесс, а начались все.
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
А если у приложения нет gui? То бишь иконка в трее только, но окна нет.
Если в трее есть иконка, то есть и главное окно. Просто оно скрыто.
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
InnI
Исправил предыдущий свой ответ (не увидел, что уже ответили)
 

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
БлагоѨръ сказал(а):
Не пойму, как сделать.

Попробуйте еще:
Код:
#include <WinAPIProc.au3>
#include <WinAPISysWin.au3>
#include <WindowsConstants.au3>

$iPID = ProcessWait('punto.exe')
$aProcWindows = _WinAPI_EnumProcessWindows($iPID, False)
If @error Then
	;ProcessClose($iPID)
Else
 	For $i = 1 To $aProcWindows[0][0]
		_WinAPI_PostMessage($aProcWindows[$i][0], $WM_CLOSE, 0, 0)
	Next
EndIf
 

InnI

AutoIT Гуру
Сообщения
4,951
Репутация
1,446
БлагоѨръ [?]
указал конкретный процесс, а начались все
Первым параметром _WinAPI_PostMessage() должен быть дескриптор окна, а не заголовок. Просто верните из функции $list[$i][1]
 
Автор
BlagoYar

BlagoYar

Русь Великая, Очнись! Поднимись с колен Родная!
Сообщения
99
Репутация
-1
InnI [?]
Первым параметром _WinAPI_PostMessage() должен быть дескриптор окна, а не заголовок. Просто верните из функции $list[$i][1]
поробовал так
Код:
Func _Process2Win($pid)
    if IsString($pid) then $pid = ProcessExists($pid)
    if $pid = 0 then return -1
    $list = WinList($pid)
    for $i = 1 to $list[0][0]
        if $list[$i][0] <> "" AND BitAnd(WinGetState($list[$i][1]),2) then
            $wpid = WinGetProcess($list[$i][0])
            if $wpid = $pid then return $list[$i][1]
        EndIf
    Next
    Return -1
EndFunc

Попробовал, но результат тот же - всё закрывается.

xXx [?]
Попробуйте еще:
То что нужно. БлагоДарю! :smile: :ok:

ПС. Ещё бы для мульти-процессов как сделать?
 
Верх