我需要知道用戶何時切換到登錄屏幕(由ctrl-alt-del觸發)in order to circumvent a pesky bug in WPF。我想通過從登錄屏幕返回後重新初始化我的GUI來解決這個bug。目前它可以工作,但我必須手動觸發它。如何檢測用戶何時切換到登錄屏幕?
我找到了SystemEvents.SessionSwitch,但不幸的是這只是在註銷時觸發的。
如何通過形成ctrl-alt-del來檢測登錄屏幕何時顯示?
我需要知道用戶何時切換到登錄屏幕(由ctrl-alt-del觸發)in order to circumvent a pesky bug in WPF。我想通過從登錄屏幕返回後重新初始化我的GUI來解決這個bug。目前它可以工作,但我必須手動觸發它。如何檢測用戶何時切換到登錄屏幕?
我找到了SystemEvents.SessionSwitch,但不幸的是這只是在註銷時觸發的。
如何通過形成ctrl-alt-del來檢測登錄屏幕何時顯示?
它獲取開始顯示登錄屏幕的過程好像是叫LogonUI.exe
。使用Windows Management Instrumentation (WMI) infrastructure您可以偵聽啓動和關閉的進程。您需要參考System.Management
組件。
var interval = new TimeSpan(0, 0, 1);
const string isWin32Process = "TargetInstance isa \"Win32_Process\"";
// Listen for started processes.
WqlEventQuery startQuery
= new WqlEventQuery("__InstanceCreationEvent", interval, isWin32Process);
_startWatcher = new ManagementEventWatcher(startQuery);
_startWatcher.Start();
_startWatcher.EventArrived += OnStartEventArrived;
// Listen for closed processes.
WqlEventQuery stopQuery
= new WqlEventQuery("__InstanceDeletionEvent", interval, isWin32Process);
_stopWatcher = new ManagementEventWatcher(stopQuery);
_stopWatcher.Start();
_stopWatcher.EventArrived += OnStopEventArrived;
處理這些事件,您可以獲取有關啓動或關閉過程的信息。這樣,您可以驗證LogonUI.exe
何時關閉,並隨後觸發所需的操作。
void OnStopEventArrived(object sender, EventArrivedEventArgs e)
{
var o = (ManagementBaseObject)e.NewEvent[ "TargetInstance" ];
string name = (string)o[ "Name" ];
...
}
棘手的是,這不是會話更改,而只是桌面更改。特別是,Ctrl + Alt + Del切換到與Winlogon相關的安全桌面。
我不認爲你真的假設來檢測這種事情(畢竟,有一個「安全桌面」的整點),但你可以使用Active輔助功能鉤子。致電SetWinEventHook
function爲EVENT_SYSTEM_DESKTOPSWITCH
event安裝事件掛接並查看您收到的通知。
要得到它去,你需要做到以下幾點:
WINEVENT_OUTOFCONTEXT
標誌,因爲您正在使用託管代碼。您不希望系統嘗試將包含回調函數的DLL注入到每個進程中。相反,這將導致回調函數從隊列異步調用;從託管代碼的土地更安全。一點P/Invoke魔法。爲了讓你開始…
const uint WINEVENT_OUTOFCONTEXT = 0x0;
const uint EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin,
uint eventMax,
IntPtr hmodWinEventProc,
WinEventDelegate lpfnWinEventProc,
uint idProcess,
uint idThread,
uint dwFlags);
delegate void WinEventDelegate(IntPtr hWinEventHook,
uint event,
IntPtr hwnd,
int idObject,
int idChild,
uint dwEventThread,
uint dwmsEventTime);
[DllImport("user32.dll")]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
很好,這似乎是一種可能的解決方案。目前我正在探索是否可以跟蹤LogonUI.exe。如果我在那裏撞牆,我會嘗試一下。 –
我結束了[非常快速的非P/Invoke實現](http://stackoverflow.com/a/10607062/590790)。除非你看到任何問題,否則我會保留那一個作爲接受的答案。到目前爲止,它對我來說工作得很好。儘管如此,這個答案非常感謝! –
@Steven不,WMI沒什麼問題。它通常是鉤子的替代品,有時候更方便編碼,尤其是在大多數基礎設施已經存在的.NET語言中(即,它們已經隱藏了BCL中的P/Invoke代碼)。唯一值得關注的問題是,它要求所有目標機器都啓用WMI服務,但是如果您正在運行安裝程序或其他軟件,則可以確保在當時正確配置它們。 –