Сохранение данных при завершении работы Windows - PullRequest
2 голосов
/ 02 июля 2019

Мое приложение (Windows 7, Visual C ++, Release-Build) должно записывать некоторые данные при закрытии окон (перезапуск, выход пользователя из системы).В конце концов, я хочу сделать то же самое, что и при получении WM_CLOSE -Message, которое вызывается во время обычного закрытия моего приложения (Alt-f4, закрытие окна, ...)

Я ненужен какой-нибудь пользовательский ввод, диалоги и тд.Просто тихое написание.Сама запись должна длиться менее секунды.

Для этого я делаю следующее:

LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
  if (message == WM_CLOSE){
    TRACE(_T("got WM_CLOSE"));
    SaveMyData();
  }

  switch (message) {
    case WM_QUERYENDSESSION:
        TRACE(_T("findme: WM_QUERYENDSESSION"));
        {
                BOOL bShutdownBlocked = ShutdownBlockReasonCreate(theApp.m_pMainWnd->GetSafeHwnd(), _T("Save data"));
                TRACE(_T("blocked: %d, GetlastError: %d"), bShutdownBlocked, GetLastError());
        }

        //continue shutdown-sequence
        return TRUE;

    case WM_ENDSESSION:
        TRACE(_T("findme: WM_ENDSESSION. Store? %d"), FALSE != (BOOL)wParam);
        if (FALSE != (BOOL)wParam) 
        {
          long lTickStart = GetTickCount();
          TRACE(_T(">>> Sleep..."));
          ::Sleep(1000); //just a Test: do something while shutting down
          TRACE(_T("<<< Sleep: %d ms"), GetTickCount()-lTickStart);

          BOOL bUnblockShutdown = ShutdownBlockReasonDestroy(theApp.m_pMainWnd->GetSafeHwnd());
          TRACE(_T("unblock: %d"), bUnblockShutdown);
        }
        return 0L;

    default:
        return CMDIFrameWnd::WindowProc(message, wParam, lParam);
    }
}

Все трассировки перенаправляются в файл, который я проверяю.

Я проверил это с помощью Restart Manager из инструментов тестирования логотипа для Windows под Win7 (rmtool -S -pid), и он отлично работает.Я получаю следующий Trace-Output:

findme: WM_QUERYENDSESSION
blocked 1, GetlastError: 0
findme: WM_ENDSESSION. Store? 1
>>> Sleep...
<<< Sleep: 1015 ms
unblock: 1
got WM_CLOSE

Обратите внимание на "полученный WM_CLOSE", который вызывает код для сохранения моих данных.

Но он не работает, когда я фактически закрываю окна иливыйдите из системы или используйте rmtool с опцией -lr.В этом случае я просто получаю следующий вывод:

findme: WM_QUERYENDSESSION
blocked 1, GetlastError: 0
findme: WM_ENDSESSION. Store? 1
>>> Sleep...
<<< Sleep: 1000 ms
unblock: 1

Здесь сообщение WM_CLOSE не получено.

Неправильно ли полагаться на это Сообщение при выключении или что я делаю неправильно?

Ответы [ 2 ]

1 голос
/ 02 июля 2019

Как MSDN говорит

Когда приложение возвращает TRUE для WM_QUERYENDSESSION, оно получает сообщение WM_ENDSESSION и завершается независимо от того, как другие приложения отвечают на сообщение WM_QUERYENDSESSION.

MSDN не указывает, что Windows завершает работу вашего приложения, отправляя ему WM_CLOSE. Вы должны сделать сохранение в обработчике WM_ENDSESSION, чтобы быть в безопасности.

Кстати, вы должны удалить звонок на ShutdownBlockReasonCreate. Какая польза от этого? Если бы это сработало, вы бы больше не получили WM_ENDSESSION. Эта функция должна вызываться заранее, если вы хотите предотвратить отключение.

0 голосов
/ 02 июля 2019

Я думаю, уловка в том, чтобы делать все правильно в WM_ENDSESSION, не отправляя и не получая никаких Windows-сообщений.

Также вам не следует слишком полагаться на rmtool.exe, по крайней мере, при использовании без -l -Параметра.Это просто ведет себя иначе, чем закрытие окон.Таким образом, чтобы протестировать сценарии выключения, вам действительно нужно завершить работу (выйти из системы, перезагрузить компьютер), а не просто имитировать его.

...