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にくれます。また、GetLastError5 (アクセスが拒否された) ではなく 0 であるため、WTS_SESSION_UNLOCK 通知を受け取る前に、セキュリティで保護されたデスクトップがなくなっていることは確かです。

画面がロックされている間はデスクトップを切り替えることができないことはわかっていますが、デスクトップのロックが解除された後、 SwitchDesktop を呼び出すことができない「猶予期間」はありますか?

4

3 に答える 3

3

デスクトップがロックされると、この目的のために予約されている別のデスクトップに切り替わります。メッセージを受け取ったとき、そのデスクトップがまだ制御されていて、現在のデスクトップで実行していないために切り替えが許可されていない可能性は十分にあります。

于 2012-02-02T22:59:55.697 に答える
2

今はテストできませんが、呼び出しをSwitchDesktopon ではWTS_SESSION_UNLOCKなく on にしWTS_CONSOLE_CONNECTます。私が収集したものから、最初に発生し、次に「一定時間」で表示されるものに対応するWTS_SESSION_UNLOCK取得が発生します...WTS_CONSOLE_CONNECT

于 2012-01-30T20:09:06.003 に答える