Есть ли какой-нибудь способ приостановить завершение работы Windows, чтобы метод forms.closing мог завершиться?

#vb.net #windows #winforms

#vb.net #Windows #winforms

Вопрос:

Я пытаюсь поместить некоторую информацию в базу данных, когда Windows начинает выключаться. В моем приложении я обрабатываю событие Form.Closing. Однако Windows продолжит работу и завершит работу, и у моего метода нет времени для завершения. Есть ли какой-нибудь способ приостановить завершение работы достаточно долго, чтобы справиться с завершением работы? Вот мой метод, который я использую в настоящее время.

 Private Sub frmMain_Closing(sender As Object, e As FormClosingEventArgs) Handles Me.Closing
        If e.CloseReason = CloseReason.WindowsShutDown Then
            _logger.Debug("Hit frmMain_Closing1")
            NewEvent(Events.SystemShutdownNormal)
            System.Threading.Thread.Sleep(10000)
            _logger.Debug("Hit frmMain_Closing 2")
        End If
    End Sub
 

Каждый раз, когда я дважды регистрируюсь в файле журнала, используя _logger.Debug("Hit...") Однако, только при первом вызове он записывается в файл. Я пробовал метод настройки e.Cancel = True , но это, похоже, не сработало.

Комментарии:

1. Это вызывает сброс к файлу или только запись в буфер?

2. @BenVoigt Tbh, я не уверен. Я не писал эту часть. Я просто знаю, что мы используем это для входа в файл. Это единственный вызов, который я делаю, но я не уверен в механизмах, стоящих за ним.

3. Включение a Sleep может быть плохой идеей.

4. @AndrewMorton Да, с тех пор я его удалил.

5. Дни блокировки завершения работы закончились и закончились, это вообще не сработало. Вы можете включить функцию ShutdownBlockReasonCreate(), чтобы отобразить на экране сообщение, которое отображается в Windows, когда приложения отказываются завершать работу. Вам нужно будет убедить пользователя, что вы делаете что-то действительно очень важное, чтобы он не нажимал кнопку игнорировать. Как и я, он проигнорирует это, если вы потратите более 5 секунд.


Ответ №1:

Извините за эту неверную информацию.
Короче говоря, нет способа отложить или отменить завершение работы Windows. Он «красиво» коснется всех процессов для выхода, затем пройдите и уничтожьте те, которые этого не сделали. Вы можете отложить завершение работы до завершения процесса. Для этого вам необходимо использовать ShutdownBlockReasonCreate() .

Вы должны перехватить сообщение WM_QUERYENDSESSION, чтобы получить возможность что-то сделать. Вам нужно переопределить WinProc, обработать сообщение, а затем вызвать базовый WinProc. Взгляните на https://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.sessionending (v = против 110).aspx (прокрутите вниз до примечания.)

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

После того, как вы подключили WM_QUERYENDSESSION, вы должны вызвать ShutdownBlockReasonCreate() блокировку завершения работы, пока ваше приложение не завершит закрытие. После завершения вызовите ShutdownBlockReasonDestroy() . Для получения дополнительной информации см. Эту статью MSDN (прокрутите вниз до «Приложения, которые должны блокировать завершение работы, должны использовать новый API причины завершения работы»).

Объявления PInvoke можно найти здесь и здесь .

Комментарии:

1. Вы можете перехватить сообщение и предложить пользователю отменить завершение работы, а затем программно завершить работу после завершения очистки. Что-то вроде этого: Private Const WM_QUERYENDSESSION Как System.Int32 = amp;H11 Private Const WM_CANCELMODE Как System.Int32 = amp;H1F Защищенный переопределяет Sub WndProc(ByRef ex как сообщение) Если ex.Msg = WM_QUERYENDSESSION, то «отмените сообщение MsgBox(«Пожалуйста, отмените завершение работы», MsgBoxStyle. Информация) Система. Диагностика. Процесс. Начать («cmd.exe «, «/ c shutdown / s») Завершить, если End Sub

2. @Neelix повторно отправил мой ответ. MS создала новые API для решения этой проблемы.

3. Да, я поиграл с этим сегодня. Мне пришлось изменить настройки реестра, чтобы разрешить программам приостанавливать завершение работы. Я следовал методу, найденному здесь: trishtech.com/2011/07/… Как только я это сделал, я мог бы использовать ShutdownBlockReasonCreate() для создания причины в Frm_Load, и моя программа могла работать, пока я не вызвал ShutdownBlockReasonDestroy() метод. Спасибо за помощь.

4. Приятно! Также спасибо за комментарий с настройкой реестра.