Что заставляет SwitchDesktop не работать сразу после того, как пользователь разблокирует сеанс? - PullRequest
6 голосов
/ 31 декабря 2011

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

В целях тестирования я поместил кнопку в простое приложение win32, которое запускает переключатель.Это работает, и закрывая запущенный процесс (блокнот), я возвращаюсь к исходному рабочему столу.

В той же программе я вызвал WTSRegisterSessionNotification, чтобы получить уведомление, когда сеанс разблокирован (WTS_SESSION_UNLOCK).Я получаю его.

Но когда я пытаюсь переключить рабочие столы в обработчике сообщений WTS_SESSION_UNLOCK, происходит сбой SwitchDesktop, и значение GetLastError равно 0. В документации говорится, что последняя ошибка обычно , а не , установленная SwitchDesktop.

Достаточно забавно, если я помещаю свой вызов для переключения рабочего стола в цикл for, он работает на 5-й итерации.

Короче говоря, это не работает:

    case WM_WTSSESSION_CHANGE:
      if(wParam == WTS_SESSION_UNLOCK)          
      {
          SwitchDesktop(a_valid_desktop_handle);
      }
    break;

Но этот уродливый хак работает:

    case WM_WTSSESSION_CHANGE:
      if(wParam == WTS_SESSION_UNLOCK)          
      {
         for(int i=0; i<10; ++i)
         {
            if(SwitchDesktop(a_valid_desktop_handle))
            {
                //This will work when i == 5, maybe 6.
                break;
            }
         }
      }
    break;

Установка таймера (для выхода из цикла сообщений) также работает, но это просто более запутанная форма цикла в отношении этой проблемы.SwitchDesktop будет работать после нескольких сообщений WM_TIMER.Это выглядит как постоянное время, хотя я не измерял его.

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

wchar_t name[512];
GetUserObjectInformation(GetThreadDesktop(GetCurrentThreadId()), UOI_NAME, name, sizeof(name)/sizeof(*name), 0);
OutputDebugString(name);

Дает мне default все время.И поскольку GetLastError равно 0, а не 5 (доступ запрещен), я почти уверен, что безопасный рабочий стол пропал до Я получаю уведомление WTS_SESSION_UNLOCK.

Я знаю, что не могу переключить рабочий столпока экран заблокирован, но существует ли «льготный период» после разблокировки рабочего стола, когда я не могу вызвать SwitchDesktop?

Ответы [ 3 ]

3 голосов
/ 03 февраля 2012

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

2 голосов
/ 31 января 2012

Я не могу проверить это прямо сейчас, но я бы положил вызов SwitchDesktop не на WTS_SESSION_UNLOCK, а на WTS_CONSOLE_CONNECT. Из того, что я собираю, сначала происходит WTS_SESSION_UNLOCK, а затем вы получаете WTS_CONSOLE_CONNECT, которое будет соответствовать тому, что вы видите с "временем ожидания" ...

0 голосов
/ 15 февраля 2018

Произошел сбой SwitchDesktop (с ошибкой 0), поскольку (согласно MSDN) он принадлежит оконной станции, которая (пока) не видна. Я не знаю ни одного уведомления пользователя о том, что «HWINSTA становится видимым».

...