我正在写一个应用程序,它有时会以toaster messages的形式发送通知给用户。
如果用户不在那里,他就看不到通知。所以我想要做的是能够检查用户是否锁定了屏幕,或者屏幕保护程序是否恰好被激活。
在用户无法看到时触发的任何通知都将被延迟,并在用户重新登录并恢复其会话时显示。
我自己使用的是Windows7,但我更喜欢适用于Windows XP及更高版本的解决方案。
发布于 2010-10-17 21:21:53
没有记录在案的方法来确定工作站当前是否已锁定。但是,当它解锁时,您可以收到通知。订阅SystemEvents.SessionSwitch事件,您将获得SessionSwitchReason.SessionLock和解锁。
侦察救星也很麻烦。当屏幕保护程序打开时,您的主窗口将收到WM_SYSCOMMAND消息SC_SCREENSAVE。您可以调用SystemParametersInfo来检查它是否正在运行。您可以在我的this thread答案中找到此问题的示例代码。
没有好的方法来找出用户是否睡着了。
发布于 2012-03-25 17:01:24
我最近在previous blog post上再次检查了这段代码,以确保它可以在Windows XP到7、x86和x64的版本上运行,并对其进行了一些清理。
以下是检查工作站是否锁定以及屏幕保护程序是否正在运行的最新极简主义代码,其中包含两个易于使用的静态方法:
using System;
using System.Runtime.InteropServices;
namespace BrutalDev.Helpers
{
public static class NativeMethods
{
// Used to check if the screen saver is running
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SystemParametersInfo(uint uAction,
uint uParam,
ref bool lpvParam,
int fWinIni);
// Used to check if the workstation is locked
[DllImport("user32", SetLastError = true)]
private static extern IntPtr OpenDesktop(string lpszDesktop,
uint dwFlags,
bool fInherit,
uint dwDesiredAccess);
[DllImport("user32", SetLastError = true)]
private static extern IntPtr OpenInputDesktop(uint dwFlags,
bool fInherit,
uint dwDesiredAccess);
[DllImport("user32", SetLastError = true)]
private static extern IntPtr CloseDesktop(IntPtr hDesktop);
[DllImport("user32", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SwitchDesktop(IntPtr hDesktop);
// Check if the workstation has been locked.
public static bool IsWorkstationLocked()
{
const int DESKTOP_SWITCHDESKTOP = 256;
IntPtr hwnd = OpenInputDesktop(0, false, DESKTOP_SWITCHDESKTOP);
if (hwnd == IntPtr.Zero)
{
// Could not get the input desktop, might be locked already?
hwnd = OpenDesktop("Default", 0, false, DESKTOP_SWITCHDESKTOP);
}
// Can we switch the desktop?
if (hwnd != IntPtr.Zero)
{
if (SwitchDesktop(hwnd))
{
// Workstation is NOT LOCKED.
CloseDesktop(hwnd);
}
else
{
CloseDesktop(hwnd);
// Workstation is LOCKED.
return true;
}
}
return false;
}
// Check if the screensaver is busy running.
public static bool IsScreensaverRunning()
{
const int SPI_GETSCREENSAVERRUNNING = 114;
bool isRunning = false;
if (!SystemParametersInfo(SPI_GETSCREENSAVERRUNNING, 0, ref isRunning, 0))
{
// Could not detect screen saver status...
return false;
}
if (isRunning)
{
// Screen saver is ON.
return true;
}
// Screen saver is OFF.
return false;
}
}
}UPDATE:根据评论中的建议更新代码。
当工作站被锁定时,OpenInputDesktop方法不会返回句柄,因此我们可以依靠OpenDesktop来获取句柄,以确保通过尝试切换来锁定它。如果它没有被锁定,那么你的默认桌面将不会被激活,因为OpenInputDesktop将为你正在查看的桌面返回一个有效的句柄。
发布于 2010-10-17 21:10:01
使用SystemParametersInfo检测屏幕保护程序是否正在运行-调用类型为SPI_GETSCREENSAVERRUNNING。这在Win2000及更高版本上受支持。
在StackOverflow here上有来自@dan_g的代码来检查wksta是否被锁定。
https://stackoverflow.com/questions/3953297
复制相似问题