10

DUPLICATE: How can I programmatically determine if my workstation is locked?

How can I detect (during runtime) when a Windows user has locked their screen (Windows+L) and unlocked it again. I know I could globally track keyboard input, but is it possible to check such thing with environment variables?

Community
  • 1
  • 1

4 Answers4

20

A SessionSwitch event may be your best bet for this. Check the SessionSwitchReason passed through the SessionSwitchEventArgs to find out what kind of switch it is and react appropriately.

Ben S
  • 68,394
  • 30
  • 171
  • 212
3

You can get this notification via a WM_WTSSESSION_CHANGE message. You must notify Windows that you want to receive these messages via WTSRegisterSessionNotification and unregister with WTSUnRegisterSessionNotification.

These posts should be helpful for a C# implementation.

http://pinvoke.net/default.aspx/wtsapi32.WTSRegisterSessionNotification

http://blogs.msdn.com/shawnfa/archive/2005/05/17/418891.aspx

http://bytes.com/groups/net-c/276963-trapping-when-workstation-locked

Andrew Grant
  • 58,260
  • 22
  • 130
  • 143
  • -1: The managed code version of this was posted before the Win32 version was... why is this even marked as the correct answer? – Powerlord Mar 02 '09 at 19:13
  • 2
    IMO, pinvoke is a last case solution when using .NET. It's better to use methods built into the Framework first. – Powerlord Mar 02 '09 at 21:18
  • 1
    I don't disagree, I just wasn't aware there was an alternative .net method. I've no idea why you cry babies see it as a reason to start downvoting though. – Andrew Grant Mar 02 '09 at 22:03
2

You can use ComponentDispatcher as an alternative way to get those events.

Here's an example class to wrap that.

public class Win32Session
{
    private const int NOTIFY_FOR_THIS_SESSION = 0;
    private const int WM_WTSSESSION_CHANGE = 0x2b1;
    private const int WTS_SESSION_LOCK = 0x7;
    private const int WTS_SESSION_UNLOCK = 0x8;

    public event EventHandler MachineLocked;
    public event EventHandler MachineUnlocked;

    public Win32Session()
    {
        ComponentDispatcher.ThreadFilterMessage += ComponentDispatcher_ThreadFilterMessage;
    }

    void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)
    {
        if (msg.message == WM_WTSSESSION_CHANGE)
        {
            int value = msg.wParam.ToInt32();
            if (value == WTS_SESSION_LOCK)
            {
                OnMachineLocked(EventArgs.Empty);
            }
            else if (value == WTS_SESSION_UNLOCK)
            {
                OnMachineUnlocked(EventArgs.Empty);
            }
        }
    }

    protected virtual void OnMachineLocked(EventArgs e)
    {
        EventHandler temp = MachineLocked;
        if (temp != null)
        {
            temp(this, e);
        }
    }

    protected virtual void OnMachineUnlocked(EventArgs e)
    {
        EventHandler temp = MachineUnlocked;
        if (temp != null)
        {
            temp(this, e);
        }
    }
}
Owen Johnson
  • 2,416
  • 2
  • 19
  • 23
-3

You absolutely don't need WM_WTSSESSION_CHANGE Just use internal WTTS apis.