#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. Приятно! Также спасибо за комментарий с настройкой реестра.