2011-12-31 4 views
6

У меня есть программа, которая переключает рабочий стол и запускает новый процесс. Когда процесс завершается, родительский процесс восстанавливает исходный рабочий стол.Что делает 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 documentation for 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?

ответ

2

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

+0

+1 для хорошей идеи, но не совсем ответ ... Вызов SwitchDesktop на WTS_CONSOLE_CONNECT работает в первый раз, каждый раз. Но WTS_CONSOLE_CONNECT не вызывается, когда пользователь блокирует и разблокирует свой сеанс. Чтобы вызвать WTS_CONSOLE_CONNECT, я должен выбрать «Switch user» в меню CTRL-ALT-DEL.Я возвращаюсь к защищенному рабочему столу со всеми плитами пользователя. Я могу войти в систему с одним и тем же пользователем, и я получу WTS_CONSOLE_CONNECT. – ixe013

+0

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

+0

Я сделал что-то, что работало на всех компьютерах, на которых я тестировался, но это квалифицируется как взлом, а не решение. Я в основном делал две вещи. 1. Я добавил 'WTS_CONSOLE_CONNECT' в выражении' switch' моего вопроса, руководствуясь Yahia. 2. После переключения (независимо от результата) я запускаю процесс на рабочем столе * new *. Этот новый процесс также пытается переключить рабочий стол. Другими словами, первый процесс пытается «подтолкнуть» пользователя к новому рабочему столу, а второй пытается «потянуть» его. Переключение всегда выполняется в петле. + Вопрос все еще остается без ответа, @CCInc! – ixe013

3

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

+0

Возможно, действительно. Я использовал отметку времени OutputDebugString, чтобы проверить это, но я добавлю код, который специально проверяет это. Будьте на связи ! – ixe013

+0

@ ixe013: Вы можете запустить этот тест? Я должен наградить эту награду и хочу знать, какой ответ был вам наиболее полезен. –

+0

@BenVoigt Я бы сказал, что Яхия заслуживает щедрости. Спасибо, я задержу его! – ixe013

0

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