Как программно завершить программу

И это работает. Теперь я хочу закрыть его из другого потока. Как я могу это сделать?

Thread.new do if it_is_time_to_finish # How? end end
Комментарии (2)
13.06.2018 08:48

Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на.

Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать как App.quit! , так и App.stop! .

13.06.2018 11:14
Ответ принят как подходящий

Благодаря эта линия вы можете использовать App.quit! или его псевдоним App.stop! .

13.06.2018 11:30

Другие вопросы по теме

Sinatra не запускает очень простую демонстрацию, template_cache равен нулю
Sinatra отображает шаблоны .md.erb, если они есть, в противном случае .md
Почему внутри помощника Sinatra не работает require_all?
Передать атрибут HTML через ajax в серверный Ruby
Класс Ruby, производный от Sinatra :: Base, имеет частные методы, но они исчезают в консоли irb.

ваша копия Windows не является подлинной! Решение 100%

Encoding :: UndefinedConversionError из ASCII-8BIT в UTF-8 в sinatra 2
Padrino многопользовательский url для одного кода маршрута

Как ограничить количество символов / слов в строковом значении базы данных в Sinatra / Active Record?

Источник: reddeveloper.ru

Как программно завершить другое приложение?

Чтобы аккуратно завершить приложение, дав ему произвести необходимую очистку, мы должны послать сообщение WM_CLOSE всем видимым окнам верхнего уровня, принадлежащим приложению. Посылка сообщения WM_CLOSE эквивалентна команде Закрыть системного меню окна. Если приложение написано правильно, то оно освободит ресурсы и завершится. Мы должны быть готовы к тому, что процесс завершения может затянуться. Hапример, приложение может спросить у пользователя, хочет ли он сохранить измененные файлы. Если приложение не завершится за разумное время, нам не останется ничего, кроме как применить «тяжелую артиллерию» — функцию TerminateProcess .

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

#define KILLAPP_TERMINATE -1 #define KILLAPP_WAIT 0 #define KILLAPP_CANCEL 1 typedef int (CALLBACK * PFNWAITCALLBACK)(LPARAM); BOOL KillApplication( IN HWND hWnd, // идентификатор окна IN PFNWAITCALLBACK pfnWaitCallback, // пользовательская функция IN LPARAM lParam // параметр для пользовательской функции );

Параметр hWnd идентифицирует приложение, которое мы хотим завершить, это может быть любое окно, принадлежащее приложению. Параметр pfnWaitCallback задает пользовательскую функцию, которая будет периодически вызываться в процессе ожидания. Программа может использовать эту фунцию для обработки сообщений, пока функция ожидает завершения останавливаемого процесса. Кроме того, пользовательская функция определяет, когда уже достаточно ждать и пора применить грубую силу: возвращаемое значение функции определяет дальнейшее поведение KillApplication :

Обнаружение и удаление скрытого майнера #майнер

KILLAPP_TERMINATE Немедленно завершить процесс с помощью TerminateProcess
KILLAPP_WAIT Продолжить ожидание
KILLAPP_CANCEL Отменить операцию и вернуть управление, не дожидаясь завершения приложения

Параметр lParam передается пользовательской функции без изменений.

Ниже приведена реализация функции KillApplication :

Читайте также:
Виды программ субд Microsoft sql server Microsoft powerpoint Microsoft access Microsoft excel

BOOL KillApplication( IN HWND hWnd, IN PFNWAITCALLBACK pfnWaitCallback, IN LPARAM lParam ) < _ASSERTE(pfnWaitCallback != NULL); if (!IsWindow(hWnd)) return SetLastError(ERROR_INVALID_PARAMETER), FALSE; // определяем идентификатор процесса и потока, которым // принадлежит указанное окно DWORD dwProcessId; DWORD dwThreadId = GetWindowThreadProcessId(hWnd, OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); // определяем версию операционной системы GetVersionEx( // проверяем, не является ли это приложение 16-битной задачей // на Windows NT BOOL b16bit = FALSE; HINSTANCE hVdmDbg = NULL; if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) < // загружаем VDMDBG.DLL hVdmDbg = LoadLibrary(_T(«vdmdbg.dll»)); if (hVdmDbg == NULL) return FALSE; b16bit = IsWOWProcess(hVdmDbg, dwProcessId); > if (!b16bit) < // открываем описатель процесса HANDLE hProcess = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwProcessId); if (hProcess == NULL) < DWORD dwError = GetLastError(); if (hVdmDbg != NULL) FreeLibrary(hVdmDbg); return SetLastError(dwError), FALSE; > // посылаем сообщение WM_CLOSE всем видимым окнам, принадлежащим // процессу EnumWindows(KillAppEnumWindows, dwProcessId); // основной цикл ожидания int nRet = KILLAPP_WAIT; while (WaitForSingleObject(hProcess, 100) == WAIT_TIMEOUT) < nRet = pfnWaitCallback(lParam); if (nRet != KILLAPP_WAIT) break; > // завершаем процесс, если пользовательская функция // решила поступить таким образом if (nRet == KILLAPP_TERMINATE) TerminateProcess(hProcess, (UINT)-1); CloseHandle(hProcess); > else < // посылаем сообщение WM_CLOSE всем окнам верхнего уровня, // принадлежащим тому же потоку EnumWindows(KillAppEnumWindows16, dwThreadId); // ожидаем, пока 16-битное приложение не завершился int nRet = KILLAPP_WAIT; WORD wTaskId; while ((wTaskId = IsWOWTask(hVdmDbg, dwProcessId, dwThreadId)) != 0) < Sleep(100); nRet = pfnWaitCallback(lParam); if (nRet != KILLAPP_WAIT) break; > // завершаем задачу принудительно if (nRet == KILLAPP_TERMINATE) TerminateWOWTask(hVdmDbg, dwProcessId, wTaskId); > if (hVdmDbg != NULL) FreeLibrary(hVdmDbg); return TRUE; >

Сначала функция определяет идентификаторы процесса и потока, которым принадлежит указанное окно — они нам пригодятся в дальнейшем для идентификации останавливаемого приложения. Затем функция проверяет, не принадлежит ли указанное окно 16-битной задаче в Windows NT. 16-битные задачи требуют специальной обработки и мы рассмотрим их отдельно.

В 32-битном случае, функция открывает описатель (handle) процесса с правами доступа SYNCHRONIZE и PROCESS_TERMINATE. Если мы не имеем таких прав по отношению к завершаемому процессу, функция сразу же завершается с ошибкой. Затем функция рассылает сообщение WM_CLOSE всем окнам верхнего уровня, принадлежащим этому процессу, для чего мы используем EnumWindows , указав в качестве функции перечисления функцию KillAppEnumWindows , текст которой приведен ниже.

static BOOL CALLBACK KillAppEnumWindows( IN HWND hWnd, IN LPARAM lParam ) < _ASSERTE(lParam != 0); DWORD dwProcessId; GetWindowThreadProcessId(hWnd, if (IsWindowVisible(hWnd) dwProcessId == (DWORD)lParam) PostMessage(hWnd, WM_CLOSE, 0, 0); return TRUE; >

После того, как сообщения разосланы, функция переходит в цикл ожидания. Каждые 100 миллисекунд она вызывает пользовательскую функцию, давая ей возможность обработать накопившиеся сообщения и принять решение, стоит ли продолжать ожидание. Выход из цикла происходит, когда случится одно из двух событий: процесс завершится и WaitForSingleObject вернет WAIT_OBJECT_0, либо пользовательская функция вернет значение, отличное от KILLAPP_WAIT. Если возвращаемым значением пользовательской функции было KILLAPP_TERMINATE, то процесс завершается принудительно с помощью TerminateProcess .

Как уже отмечалось, 16-битные задачи обрабатываются особенным образом. Главное их отличие от 32-битных задач для нас состоит в том, что несколько 16-битных задач могут разделять один процесс WOW VDM, поэтому та логика, которую мы использовали для завершения 32-битных приложений является непригодной. Прежде всего, вот код функции IsWOWProcess , которая используется для того, чтобы отличить 16-битные задачи:

Читайте также:
Программа не отображает русские символы

static BOOL CALLBACK EnumProcessWOWProc( IN DWORD dwProcessId, IN DWORD dwAttributes, IN LPARAM lParam ) < _ASSERTE(lParam != 0); if (dwProcessId == *(DWORD *)lParam) < *(DWORD *)lParam = 0; return TRUE; > return FALSE; > static BOOL IsWOWProcess( IN HINSTANCE hVdmDbg, IN DWORD dwProcessId ) < _ASSERTE(hVdmDbg != NULL); _ASSERTE(dwProcessId != 0); int (WINAPI * _VDMEnumProcessWOW)(PROCESSENUMPROC, LPARAM); *(FARPROC *)VDMEnumProcessWOW»); _ASSERTE(_VDMEnumProcessWOW != NULL); _VDMEnumProcessWOW(EnumProcessWOWProc, (LPARAM) return dwProcessId == 0; >

IsWOWProcess перечисляет все виртуальные DOS-машины WOW с помощью функции VDMEnumProcessWOW из VDMDBG.DLL. Если окно, указанное в качестве параметра KillApplication , принадлежит одному из этих процессов, значит, мы имеем дело с 16-битной задачей.

Для 16-битных задач мы тоже рассылаем сообщение WM_CLOSE всем окнам верхнего уровня этой задачи, но теперь мы ориентируемся не по идентификатору процесса, а по идентификатору потока, поскольку процесс виртуальной DOS-машины может содержать несколько 16-битных задач, каждая из которых выполняется в своем потоке. Для рассылки WM_CLOSE мы используем EnumWindows с функцией KillAppEnumWindows16 в качестве функции перечисления:

static BOOL CALLBACK KillAppEnumWindows16( IN HWND hWnd, IN LPARAM lParam ) < _ASSERTE(lParam != 0); if (IsWindowVisible(hWnd) GetWindowThreadProcessId(hWnd, NULL) == (DWORD)lParam) PostMessage(hWnd, WM_CLOSE, 0, 0); return TRUE; >

В случае 16-битных задач мы не можем использовать описатель процесса для ожидания завершения задачи, поскольку процесс виртуальной DOS-машины может и не завершиться, если в нем остались другие задачи. Для определения факта завершения задачи мы используем функцию IsWOWTask , которая в качестве побочного эффекта возвращает идентификатор задачи.

typedef struct _WOWTASKENUM < DWORD dwThreadId; WORD wTaskId; >WOWTASKENUM, * PWOWTASKENUM; static BOOL CALLBACK EnumTaskWOWProc( IN DWORD dwThreadId, IN WORD hMod16, IN WORD hTask16, IN LPARAM lParam ) < PWOWTASKENUM pTaskEnum = (PWOWTASKENUM)lParam; _ASSERTE(pTaskEnum != NULL); if (dwThreadId == pTaskEnum->dwThreadId) < pTaskEnum->wTaskId = hTask16; return TRUE; > return FALSE; > static WORD IsWOWTask( IN HINSTANCE hVdmDbg, IN DWORD dwProcessId, IN DWORD dwThreadId ) < _ASSERTE(hVdmDbg != NULL); _ASSERTE(dwProcessId != 0); _ASSERTE(dwThreadId != 0); int (WINAPI * _VDMEnumTaskWOW)(DWORD, TASKENUMPROC, LPARAM); *(FARPROC *)VDMEnumTaskWOW»); WOWTASKENUM wte; wte.dwThreadId = dwThreadId; wte.wTaskId = 0; _VDMEnumTaskWOW(dwProcessId, EnumTaskWOWProc, (LPARAM) return wte.wTaskId; >

IsWOWTask полагается на функцию VDMEnumTaskWOW , экспортируемую из VDMDBG.DLL, которая была рассмотрена в статье Как перечислить 16-битные задачи под Windows NT?.

Как и в случае 32-битных приложений, мы вызываем пользовательскую функцию с интервалом в 100 миллисекунд. Если пользовательская функция решает завершить задачу принудительно, мы вызываем функцию TerminateWOWTask , которая есть ни что иное как обертка вокруг VDMTerminateTaskWOW .

static BOOL TerminateWOWTask( IN HINSTANCE hVdmDbg, IN DWORD dwProcessId, IN WORD wTaskId ) < _ASSERTE(hVdmDbg != NULL); _ASSERTE(dwProcessId != 0); _ASSERTE(wTaskId != 0); BOOL (WINAPI * _VDMTerminateTaskWOW)(DWORD, WORD); *(FARPROC *)VDMTerminateTaskWOW»); return _VDMTerminateTaskWOW(dwProcessId, wTaskId); >

В заключение рассмотрим несколько вариантов реализации пользовательской функции для использования совместно с KillApplication . Первый вариант функции реализует ожидание с фиксированным таймаутом:

Читайте также:
Программа задачи с параметрами

int CALLBACK WaitCallback1( IN LPARAM lParam ) < return (GetTickCount()

Предполагается, что в качестве параметра lParam для KillApplication будет указано время окончания ожидания. Например, такой вызов приведет к 15-секундному ожиданию:

KillApplication(hWnd, WaitCallback1, GetTickCount() + 15000);

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

int CALLBACK WaitCallback2( IN LPARAM lParam ) < MSG msg; while (PeekMessage( TranslateMessage( DispatchMessage( >return (GetTickCount()

Еще более сложный вариант, который обрабатывает сообщения и отображает диалоговое окно по истечении 15 секунд ожидания, вы можете найти в исходном коде демонстрационного приложения Process Viewer, которое сопровождает эту статью.

Cсылки

  1. Q178893 HOWTO: Terminate an Application «Cleanly» in Win32 , Microsoft Knowledge Base.

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

Источник: www.rsdn.org

Как программно остановить / завершить / завершить работу / завершить работу с ядром dotnet в консольном приложении HostBuilder?

Я пытаюсь создать консольное приложение с ядром dotnet. Приложение является простым служебным приложением и должно запускаться, делать свое дело и выходить. Этого легко добиться, используя стандартный шаблон консольного приложения, сгенерированный Visual Studio. Но в наши дни у нас есть HostBuilder, который кажется более привлекательным, потому что он приносит объединяющий опыт с WebHostBuilder, DI, Loggin и т. Д.

Но похоже, что этот подход предназначен только для длительных фоновых сервисов. Это начнется и будет длиться вечно до события внешнего завершения (например, Ctrl-C).

Есть ли способ завершить этот тип приложения изнутри?

rook 27 Фев 2019 в 21:15

3 ответа

Лучший ответ

Вы можете использовать IApplicationLifetime для прекращения работы вашего приложения, вы можете получить к нему доступ из конструктора и вызвать метод StopApplication() .

IApplicationLifetime _lifeTime; public MyClass(IApplicationLifetime lifeTime)
public void Exit()
Brian Surowiec 10 Июн 2019 в 19:54

Даже если вы используете HostBuilder чтобы зарегистрировать все зависимости в вашем приложении, вам не нужно использовать IHost для запуска приложения cmd line. Вы можете просто запустить свое приложение, создав таким образом область обслуживания.

HostBuilder hostbuilder = new HostBuilder(); builder.ConfigureServices(ConfigureServices); //Configure all services for your application here IHost host = hostbuilder .Build(); using (var scope = host.Services.CreateScope()) < var myAppService = scope.ServiceProvider.GetService(typeof(IMyAppServiceToRun)) as IMyAppServiceToRun; //Use IHost DI container to obtain instance of service to run // Execute your task here >
ptat 7 Окт 2019 в 22:00

1- Используйте UseConsoleLifetime() при сборке хоста в Program.cs

Host.CreateDefaultBuilder(args).UseConsoleLifetime(opts => opts.SuppressStatusMessages = true);

2- Зарегистрированное ApplicationStopped событие. Чтобы вы могли грубо принудительно завершить приложение, вызвав метод Kill() текущего процесса.

public void Configure(IHostApplicationLifetime appLifetime) < appLifetime.ApplicationStarted.Register(() =>< Console.WriteLine(«Press Ctrl+C to shut down.»); >); appLifetime.ApplicationStopped.Register(() => < Console.WriteLine(«Terminating application. «); System.Diagnostics.Process.GetCurrentProcess().Kill(); >); >

Источник: question-it.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru