Как проверить, получила ли система вызов на отключение
Я пытаюсь разработать простой набор тестов для кода, который закрывает систему Windows. Требование состоит в том, чтобы программно определить, действительно ли система получила вызов на отключение до ее выключения (чтобы передать этот результат дальше в набор тестов), и точное время ИНИЦИАЦИИ выключения.
До сих пор я пробовал несколько разных подходов, ни один из которых не кажется удовлетворительным:
1) Мониторинг и перехват вызова WM_QueryEndSession
Недостатки: в основном этот вызов обычно используется для уведомления запущенных приложений и интерактивных пользователей о завершении работы системы. Однако этот вызов может не работать с неотвечающим приложением или службой. Или же фактическое отключение может быть отложено до тех пор, пока не отвечающие службы не будут прерваны и приложения не будут закрыты системой, даже если вызов завершен с правильным состоянием.
2) Журнал событий Windows Можно было бы разработать программу для чтения журнала событий Windows. Программе потребуется некоторое время, чтобы просмотреть журнал событий и проверить, было ли зарегистрировано соответствующее сообщение или нет. Но похоже, что это займет некоторое время и, вероятно, не завершится, прежде чем система инициирует закрытие службы регистрации событий и дальнейшее завершение работы. Более того, запуск программы во время выключения системы не кажется надежным.
3) Просто пропингуйте компьютер, чтобы убедиться, что сетевой адаптер был отключен от сети. Это не первое действие, предпринимаемое в процессе выключения, и оно может быть значительно задержано из-за неотвечающих процессов и других причин.
Есть ли надежный способ перехвата вызова системы до ее отключения?
1 ответ
Если честно, мой мозг кричит НЕТ. Вся идея кажется ошибочной. Это звучит как отчаянная попытка устранить симптом совершенно другой проблемы. Кроме того, тестирование за определенными границами, как правило, не рекомендуется, и на то есть веская причина: оно слишком усложняет ситуацию до такой степени, что оно действительно не стоит усилий. Например, в этой ситуации, когда вы тестируете завершение работы:
- Вы действительно хотите отключиться в тесте?
- А как насчет других приложений, которые не хотят, чтобы вы закрыли сейчас?
- Если вы на самом деле завершаете работу, ваше приложение, тестирующее завершение работы, будет отключаться с остальной частью системы.
- После выключения происходит автоматический перезапуск?
- Если вы используете опцию выключения для автоматического перезапуска - будет ли это так же, как производственный сценарий?
- Может быть, вам нужно правильное отключение питания и пробуждение по локальной сети, чтобы выполнить удаленный перезапуск для более реалистичного теста?
- Или, может быть, вы хотите проверить команду выключения без фактического выключения?
- Проблема в том, что как только вы отправляете команду выключения (успешно), Windows начинает выключаться.
- Вы можете прервать завершение работы, но к тому времени другие приложения могут быть закрыты в ответ на запрос (не очень дружелюбное поведение).
Это ситуация, когда обычно более уместно макетировать интерфейс к проблемной границе. Затем вы просто проверяете, что взаимодействие с макетом корректно.
Тем не менее, я все еще волнуюсь, что вы пытаетесь устранить симптомы другой проблемы.
Вы сказали: "Было несоответствие с некоторыми развертываниями Windows (хотя и не со всеми)".
Определили ли вы причину несоответствия? Если у вас есть приложение, которое должно автоматически выдавать команду завершения работы, существует ряд причин, по которым оно может не работать:
- Возможно, приложение не было запущено.
- Там может быть ошибка, которая помешала ему сделать необходимый вызов.
- Возможно, он совершил вызов, но Windows, возможно, отклонила его (надеюсь, вы проверяете возвращаемое значение вызова API?) По какой-то причине (разрешение, удаленные сеансы, ОС в середине чего-то еще - кто знает?).
- Теперь, даже если вызов возвращает результат успеха, остановка может быть остановлена. (Кстати, вы сказали, что вам нужно знать время инициализации. Вот оно! Это когда началось выключение. Запишите текущее время в файл, в реестр - все, что угодно.
- Даже с учетом всего вышеперечисленного, любое приложение может прервать процесс завершения работы. Поэтому, даже если ваш код, который отключает систему, был тщательно протестирован и работает отлично - какое-то другое совершенно не связанное приложение может развернуться и сказать: "ix-nay при завершении работы, эй!" - и система продолжает работать....
Возвращаясь к "симптому другой проблемы"... В некоторых вещах, которые вы сказали (проверяя журнал событий, заботясь о времени, говоря: "поймать, был ли в системе сделан вызов завершения работы"), вы пытаетесь выяснить после факта "была ли выдана команда выключения"?
Это не похоже на проблему тестирования - это похоже на проблему регистрации.
Возможно, вы хотите проверить, правильно ли ведется эта очень важная регистрация?
И это возвращает меня к следующему: скорее смейтесь над вызовами API Windows и проверьте правильность вашего взаимодействия с документированным API.
Если бы я не отговорил вас от насмешек над богами безумия...
Вы упомянули недостаток мониторинга WM_QueryEndSession приложений / сервисов, которые не отвечают. Тем не менее, вы не заботитесь о других приложениях. Вам нужно только одно приложение, ваше приложение. Крошечная простая утилита для мониторинга, если это необходимо. Когда он получит сообщение - запишите его вместе с причиной. (Там все еще нет гарантийного завершения, конечно.)
Вы можете пойти дальше, ваше приложение для мониторинга может использовать функцию SetProcessShutdownParameters, чтобы стать одним из первых процессов, уведомленных о завершении работы. Конечно, если завершение работы прервано, ваша утилита мониторинга больше не будет работать, и ее необходимо будет перезапустить. (Я упоминал безумие и безумие?)
В качестве альтернативы, установите его в качестве одного из последних отключений, позволяющих вам предпринять какое-то действие за раз ближе к фактическому отключению (если оно действительно отключается).
Вы беспокоились о том, что читаете журнал событий, потому что он может быть слишком медленным, чтобы завершить работу, когда система выключается. Почему вы даже хотите прочитать его во время выключения? (Или это безумие уже завладело?) Скорее всего, данные не уйдут, пока диски отключаются, ничего не делая. Прочитайте его при перезагрузке, если это необходимо. Но сначала прочитайте об отключении событий Tracker.
Наконец, вместо (или в дополнение к) прослушивания WM_QueryEndSession, прослушивайте WM_EndSession. В некоторых ситуациях первое не будет отправлено. Но, насколько я могу судить, последнее всегда нужно отправлять.
Я упоминал безумие? ... Может быть, это было безумие. ... Я знаю, что упомянул психушку. ... Что, кто, почему, когда, как? ... Они у меня в голове!
Безумие заканчивается.