デスクトップを切り替えて新しいプロセスを開始するプログラムがあります。プロセスが終了すると、親プロセスは元のデスクトップを復元します。
テスト目的で、スイッチをトリガーするプレーンな 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
5 (アクセスが拒否された) ではなく 0 であるため、WTS_SESSION_UNLOCK 通知を受け取る前に、セキュリティで保護されたデスクトップがなくなっていることは確かです。
画面がロックされている間はデスクトップを切り替えることができないことはわかっていますが、デスクトップのロックが解除された後、 SwitchDesktop を呼び出すことができない「猶予期間」はありますか?