Как изящно прекратить процесс? - PullRequest
36 голосов
/ 13 января 2010

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

Так что TerminateProcess не может быть и речи, потому что это мгновенно убивает процесс. Другой способ - использовать SendMessage / PostMessage для отправки WM_CLOSE в главное окно, к сожалению, я ничего не знаю о окнах процессов, у меня есть только идентификатор процесса, поэтому FindWindow не делает тоже не поможет. Есть ли другой способ найти главные окна процесса?

Другими словами: Есть ли способ завершить любой процесс изящно так же, как это делает менеджер задач, когда вы нажимаете « End Task »? (а не «Завершить процесс»)

Ответы [ 6 ]

25 голосов
/ 13 января 2010

EnumWindows перечисляет все окна верхнего уровня в процессе. GetWindowThreadProcessId получает процесс и идентификатор каждого потока.

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

Вы можете отправлять WM_CLOSE сообщений в любое окно, которое хотите закрыть. Многие окна обрабатывают WM_CLOSE, чтобы предложить пользователю сохранить документы. Вы можете отправить сообщение WM_QUIT, используя PostThreadMessage, в обнаруженные потоки, чтобы завершить цикл обработки сообщений.

Пользовательский код не может вызывать DestroyWindow из другого приложения или потока в Windows ... если приложение не отвечает на WM_CLOSE или WM_QUIT запросы, вы вернулись в TerminateProcess land.

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

Нет реального способа изящного закрытия консольных приложений в Windows. Они должны поддерживать какой-то изящный механизм закрытия.

15 голосов
/ 13 января 2010

Я не слишком уверен насчет API Win32, но вы можете выполнить оболочку taskkill из командной строки.

taskkill /?
taskkill /pid 1230
taskkill /im notepad.exe

Параметр / f приведет к принудительному уничтожению, но если он не используется, он просто отправляет сигнал завершения, поэтому приложение корректно закрывается.

13 голосов
/ 13 января 2010
3 голосов
/ 25 апреля 2018

Чтобы добавить к Крис Бек ответ о прекращении изящного завершения консольного процесса.

AttachConsole () для подключения к консольному приложению и отправки события прерывания управления, аналогично нажатию CTRL + C в командной строке.

Использование GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, processID).

Это событие управления должно обрабатываться в консольном приложении для корректного завершения.

1 голос
/ 23 января 2010

Используйте функцию EndTask API. Это та же функция, что используется диспетчером задач.

BOOL EndTask(      
    HWND hWnd,
    BOOL fShutDown,
    BOOL fForce
);

http://msdn.microsoft.com/en-us/library/ms633492(VS.85).aspx

0 голосов
/ 12 апреля 2019

Вы можете использовать taskkill / im your_program.exe для отправки сигнала завершения в приложение. Это вызовет WM_CLOSE в очереди сообщений Windows. Ты можешь использовать Или https://msdn.microsoft.com/en-us/library/windows/desktop/ms633573(v=vs.85).aspx или

https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage

для обработки сообщения.

Пожалуйста, обратитесь к аналогичному ответу Win32 API аналог отправки / перехвата SIGTERM

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