6

我有一个程序可以切换桌面并在其上启动一个新进程。当进程退出时,父进程恢复原始桌面。

出于测试目的,我在一个普通的 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 消息后运行。它看起来像常数时间,虽然我没有测量它。

SwitchDesktop 的 MSDN 文档提到这将因我使用的自定义 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 ?

4

3 回答 3

3

当桌面被锁定时,它会切换到另一个为此目的而保留的桌面。很有可能当您收到消息时,该桌面仍处于控制之中,并且您不能切换,因为您没有在当前桌面中运行。

于 2012-02-02T22:59:55.697 回答
2

我现在无法测试它,但我会打电话给SwitchDesktopnot onWTS_SESSION_UNLOCK但 on WTS_CONSOLE_CONNECT。从我收集到的信息WTS_SESSION_UNLOCK首先发生,然后您的 getWTS_CONSOLE_CONNECT将对应于您在“恒定时间”中看到的内容......

于 2012-01-30T20:09:06.003 回答
0

SwitchDesktop 失败(错误 0),因为(根据 MSDN)它属于(尚未)可见的窗口站。我所知道的没有用户通知说“HWINSTA 变得可见”。

于 2018-02-15T17:05:31.947 回答