Что делает SwitchDesktop не работающим сразу после того, как пользователь открывает сеанс?

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

В целях тестирования я поместил кнопку в простое приложение 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 ответа

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

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

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

Другие вопросы по тегам