[英]Alternative way to check if CTRL+ALT+DEL screen is visible
目前我正在使用下面的代碼來測試CTRL + ALT + DEL屏幕是否可見並且它是否按預期工作。 問題是輪詢此信息會消耗 CPU,我正在尋找基於事件的選項。 有誰知道另一種檢測此屏幕是否可見的方法?
我只需要知道此屏幕何時關閉。 我真的不在乎它什么時候打開。 只是它一直開放,現在關閉。
老實說,我找到了這段代碼,但我不確定它是如何具體到我所指的屏幕的,如果有的話。 它似乎在尋找任何進程創建和刪除事件。 這意味着此屏幕必須打開一個新進程。 知道進程名稱也會有幫助。
var interval = new TimeSpan(0, 0, 3);
const string isWin32Process = "TargetInstance isa \"Win32_Process\"";
// Listen for started processes.
WqlEventQuery startQuery = new WqlEventQuery("__InstanceCreationEvent", interval, isWin32Process);
var _startWatcher = new ManagementEventWatcher(startQuery);
_startWatcher.Start();
_startWatcher.EventArrived += OnStartEventArrived;
// Listen for closed processes.
WqlEventQuery stopQuery = new WqlEventQuery("__InstanceDeletionEvent", interval, isWin32Process);
var _stopWatcher = new ManagementEventWatcher(stopQuery);
_stopWatcher.Start();
_stopWatcher.EventArrived += OnStopEventArrived;
這個屏幕叫什么名字? 我如何檢測這種類型的窗口? 它似乎與登錄窗口的類型相同。
當您按CTRL + ALT + DEL 時,Windows 會切換到另一個特殊的虛擬桌面a ,該桌面托管負責用戶登錄/注銷/鎖定等操作的winlogon
進程。 通過使用帶有EVENT_SYSTEM_DESKTOPSWITCH
參數的 WinAPI 函數SetWinEventHook
,您可以設置一個回調函數,該函數在發生此類桌面切換時調用:
//Store the callback in a variable so that it is not GC'd
private static readonly WinEventDelegate callback = EventCallback;
static void StartListeningForDesktopSwitch()
{
SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH, EVENT_SYSTEM_DESKTOPSWITCH,
IntPtr.Zero, callback, 0, 0, WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNTHREAD);
}
static void EventCallback(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
Console.WriteLine("Desktop switched");
}
注意:如果你想在控制台應用程序中使用它,你必須通過添加一個隱藏的Form
來添加一個消息循環:
static void Main(string[] args)
{
StartListeningForDesktopSwitch();
// Run message loop
Application.Run(new HiddenForm());
}
private class HiddenForm : Form
{
public HiddenForm()
{
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
}
}
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread,
uint dwmsEventTime);
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
const uint WINEVENT_OUTOFCONTEXT = 0x0000;
const uint WINEVENT_SKIPOWNTHREAD = 0x0001;
const uint EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;
進一步:當用戶按下Win + L或彈出 UAC 窗口時,也會發生桌面切換。 因此,我們需要一種方法來檢測這些其他情況。 UAC案例比較簡單,在回調函數中檢查consent.exe
進程是否在運行就足夠了:
var processes = Process.GetProcessesByName("consent");
if (processes.Length == 0)
Console.WriteLine("This is not a UAC prompt");
不幸的是,另一種情況要復雜一些。 我只設法檢測到用戶是否從鎖定屏幕返回,而不是他們是否進入(如您所說,這與您無關,但無論如何我想提一下)。
檢測會話是否被鎖定,可以通過監聽來完成SystemEvents.SessionSwitch
在我們的活動HiddenForm
。 該SessionSwitchEventArgs.Reason
屬性設置為SessionSwitchReason.SessionLock
如果這是一個鎖事件,並SessionSwitchReason.SessionUnlock
如果用戶解鎖。 我們只能在切換回默認桌面時判斷桌面切換是否不是鎖定屏幕桌面,因為切換桌面事件回調是在會話鎖定之前和會話解鎖之后調用的。 這導致示例控制台應用程序的以下代碼:
private static readonly WinEventDelegate callback = EventCallback;
static void Main(string[] args)
{
SetWinEventHook(EVENT_SYSTEM_DESKTOPSWITCH,
EVENT_SYSTEM_DESKTOPSWITCH, IntPtr.Zero, callback, 0, 0,
WINEVENT_OUTOFCONTEXT | WINEVENT_SKIPOWNTHREAD);
Application.Run(new HiddenForm());
}
private class HiddenForm : Form
{
public HiddenForm()
{
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Minimized;
this.ShowInTaskbar = false;
SystemEvents.SessionSwitch += SystemEvents_SessionSwitch;
}
private void SystemEvents_SessionSwitch(object sender, SessionSwitchEventArgs e)
{
if (e.Reason == SessionSwitchReason.SessionUnlock)
wasUnlocked = true;
}
}
static bool wasUnlocked = false;
static bool wasOpened = false;
static void EventCallback(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread, uint dwmsEventTime)
{
// Check if UAC dialog is being shown
var processes = Process.GetProcessesByName("consent");
if (processes.Length == 0)
{
if (wasOpened)
{
if (!wasUnlocked)
Console.WriteLine("Exited from CTRL+ALT+DEL");
wasUnlocked = false;
wasOpened = false;
}
else
wasOpened = true;
}
}
delegate void WinEventDelegate(IntPtr hWinEventHook, uint eventType,
IntPtr hwnd, int idObject, int idChild, uint dwEventThread,
uint dwmsEventTime);
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(uint eventMin, uint eventMax, IntPtr
hmodWinEventProc, WinEventDelegate lpfnWinEventProc, uint idProcess,
uint idThread, uint dwFlags);
const uint WINEVENT_OUTOFCONTEXT = 0x0000;
const uint WINEVENT_SKIPOWNTHREAD = 0x0001;
const uint EVENT_SYSTEM_DESKTOPSWITCH = 0x0020;
a此類虛擬桌面與 Windows 10 中新引入的“虛擬桌面”功能無關
不確定這是否有幫助。 這不會檢查屏幕是否存在,而是是否已觸發事件,為此您可能需要啟用這些事件的日志記錄,您可以通過打開組策略編輯器來完成:
gpedit.msc
→計算機配置→ Windows 設置→安全設置→高級審核策略配置→系統審核策略→本地組策略對象→登錄/注銷→審核其他登錄/注銷事件
啟用后,您可以監聽事件 id 4800
用於鎖定和4801
用於解鎖。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.