I have recently checked this code again from a previous blog post to ensure it works on versions of Windows XP to 7, x86 and x64 and cleaned it up a bit.
Here is the latest minimalist code that checks if the workstation is locked and if the screensaver is running wrapped in two easy to use static methods:
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: Code updated based on suggestions in the comments.
When the workstation is locked then the OpenInputDesktop method does not return a handle so we can fall-back on OpenDesktop for a handle to make sure it's locked by trying to switch. If it's not locked then your default desktop will not be activated since OpenInputDesktop will return a valid handle for the desktop you are viewing.