WTSRegisterSessionNotification function
Applies to: desktop apps only
Registers the specified window to receive session change notifications.
Syntax
BOOL WTSRegisterSessionNotification( __in HWND hWnd, __in DWORD dwFlags );
Parameters
- hWnd [in]
-
Handle of the window to receive session change notifications.
- dwFlags [in]
-
Specifies which session notifications are to be received. This parameter can be one of the following values.
Return value
If the function succeeds, the return value is TRUE. Otherwise, it is FALSE. To get extended error information, call GetLastError.
Remarks
If this function is called before the dependent services of Remote Desktop Services have started, an RPC_S_INVALID_BINDING error code may be returned. When the Global\\TermSrvReadyEvent global event is set, all dependent services have started and this function can be successfully called.
Session change notifications are sent in the form of a WM_WTSSESSION_CHANGE message. These notifications are sent only to the windows that have registered for them using this function.
When a window no longer requires these notifications, it must call WTSUnRegisterSessionNotification before being destroyed. For every call to this function, there must be a corresponding call to WTSUnRegisterSessionNotification.
If the window handle passed in this function is already registered, the value of the dwFlags parameter is ignored.
To receive session change notifications from a service, use the HandlerEx function.
Requirements
|
Minimum supported client | Windows XP |
|---|---|
|
Minimum supported server | Windows Server 2003 |
|
Header |
|
|
Library |
|
|
DLL |
|
See also
- HandlerEx
- WTSRegisterSessionNotificationEx
- WTSUnRegisterSessionNotification
- WTSGetActiveConsoleSessionId
- WM_WTSSESSION_CHANGE
- WTSSESSION_NOTIFICATION
Send comments about this topic to Microsoft
Build date: 3/7/2012
That's because WPF Windows are already registered to receive WM_WTSSESSION_CHANGE in NOTIFY_FOR_THIS_SESSION mode.
So if in WPF you need to receive NOTIFY_FOR_THIS_SESSION - WM_WTSSESSION_CHANGE you don't need to call WTSRegisterSessionNotification.
But if you need to receive NOTIFY_FOR_ALL_SESSIONS - WM_WTSSESSION_CHANGE you first need to Call WTSUnRegisterSessionNotification and then register the Window calling WTSRegisterSessionNotification with NOTIFY_FOR_ALL_SESSIONS flag.
I've written a couple of blog articles about WTSRegisterSessionNotification, follow this links:
http://juank.black-byte.com/csharp-notificaciones-sesion-cambios/
http://juank.black-byte.com/csharp-notificacion-cambio-sesion-forms/
http://juank.black-byte.com/csharp-notificacion-cambio-sesion-wpf/
- 6/3/2011
- Juan Carlos Ruiz Pacheco
- 6/3/2011
- Juan Carlos Ruiz Pacheco
Scenario 1 (Where it works as it is supposed to):
Try calling WTSRegisterSessionNotification() with NOTIFY_FOR_THIS_SESSION flag set in your program. Then goto 'Start->Log Off' then click on 'Switch User'. Now select a new user. Then keeping this new account open (which will be required to be so for scenario 2) switch back to your original user account. You will have received WTS_SESSION_LOCK and WTS_SESSION_UNLOCK as expected; both events related to the session from where your code is running.
Scenario 2 (Where it fails to work as it is supposed to):
Now restart your program and again goto 'Start->Log Off' then 'Switch User'. This time unlock the new account you had locked earlier. Again switch to your original account to see what messages your window has got. This time too WTS_SESSION_LOCK and WTS_SESSION_UNLOCK will have been caught. But there is a problem. WTS_SESSION_LOCK is fired correctly for the original session but WTS_SESSION_UNLOCK will have been fired while unlocking the new account and no event will have fired when the user is unlocking the session where your program is running (whom you asked to be notified for its lock/unlock event).
This problem is easily confirmed if you call WTSGetActiveConsoleSessionId() when lock and unlock events are caught in your code. You will see that you get different session ids in Scenario 2 instead of being same.
Solution:
To be notified correctly of session change events concerning only your session, save session id of your process by calling GetCurrentProcessId() and ProcessIdToSessionId() function in a variable. Also, call WTSRegisterSessionNotification() with NOTIFY_FOR_ALL_SESSIONS (Even a process running under guest account can receive notifications of global session change under Windows XP SP2; not tested in any otherOS vers). When you receive WM_WTSSESSION_CHANGE message in your windows procedure, see if WTSGetActiveConsoleSessionId() and session id of your process (which you saved earlier in a variable) are equal or not. If they are equal then this event is concerned with your session.
Happy Coding,
Sanje2v
- 3/16/2009
- Sanje2v
- 5/27/2009
- Jodie-ella
Private Declare Function WTSRegisterSessionNotification Lib "Wtsapi32" (ByVal hWnd As IntPtr, ByVal THISSESS As Integer) As IntegerPrivate Const NOTIFY_FOR_ALL_SESSIONS As Integer = 1
Private Const NOTIFY_FOR_THIS_SESSION As Integer = 0
Usage:
After regustering owerride your WndProc anc catch WM_WTSSESSION_CHANGE message like this:
Private Const WM_WTSSESSION_CHANGE As Integer = &H2B1
Private Enum WTS
CONSOLE_CONNECT = 1
CONSOLE_DISCONNECT = 2
REMOTE_CONNECT = 3
REMOTE_DISCONNECT = 4
SESSION_LOGON = 5
SESSION_LOGOFF = 6
SESSION_LOCK = 7
SESSION_UNLOCK = 8
SESSION_REMOTE_CONTROL = 9
End Enum
Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
Select Case m.Msg
Case WM_WTSSESSION_CHANGE
Select Case m.WParam.ToInt32
Case WTS.CONSOLE_CONNECT
Debug.Print("A session was connected to the console session.")
Case WTS.CONSOLE_DISCONNECT
Debug.Print("A session was disconnected from the console session.")
Case WTS.REMOTE_CONNECT
Debug.Print("A session was connected to the remote session.")
Case WTS.REMOTE_DISCONNECT
Debug.Print("A session was disconnected from the remote session.")
Case WTS.SESSION_LOGON
Debug.Print("A user has logged on to the session.")
Case WTS.SESSION_LOGOFF
Debug.Print("A user has logged off the session.")
Case WTS.SESSION_LOCK
Debug.Print("A session has been locked.")
Case WTS.SESSION_UNLOCK
Debug.Print("A session has been unlocked.")
Case WTS.SESSION_REMOTE_CONTROL
Debug.Print("A session has changed its remote controlled status. To determine the status, call GetSystemMetrics and check the SM_REMOTECONTROL metric.")
End Select
End Select
MyBase.WndProc(m)
End Sub
- 9/18/2008
- Đonny
HANDLE hEvent = OpenEvent(SYNCHRONIZE, FALSE, _T("Global\\TermSrvReadyEvent"));
hEvent is set to NULL, and GetLastError returns 5 (access denied).
You can do this on Vista Business on a limited user account though.
- 6/4/2008
- Anthony Wieser