Responding to SwitchUser event in XP
Hi
It's been 2 years since I last did any programming or contributed to this forum :) I'm back with a question I hope someone can help me with.
I have an app written in MFC which can be run by multiple users logged into XP. I need to add some event handling so that when one user switches to another, the app is effectively "paused" for the user until their account is switched back to.
I can handle the "pause" part, I just need to know how my app can know that the account under which it is running is not the active desktop account.
I've found this :
WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION);
which appears to be a terminal server sdk function which will cause the message WM_WTSSESSION_CHANGE to be sent as a callback to the window with the hWnd specified above. All well and good, and probably just the ticket. Problem is, it requires _WIN32_WINNT 0x0501 to compile, and my app is set to 0x0400 because it is to run on 98 and 2k also.
So, I need some other way to detect user switching in an MFC app, that will compile on an xp system in vs2003, but will still run on a 98/2k system.
Thanks a lot for your suggestions.
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by jase jennings
All well and good, and probably just the ticket. Problem is, it requires _WIN32_WINNT 0x0501 to compile, and my app is set to 0x0400 because it is to run on 98 and 2k also.
So, I need some other way to detect user switching in an MFC app, that will compile on an xp system in vs2003, but will still run on a 98/2k system.
Do you really think it might be other way to detect? The way to detect remains the same, but the way to compile must be different. I think it should be explicit WTSRegisterSessionNotification resolving by LoadLibrary("wtsapi32.dll")+GetProcAddress(..., "WTSRegisterSessionNotification"). :)
In case you don't find wtsapi32.dll you may be sure it's no user switching present in system.
End explicit function address resolution never could stop your compile with 0x0400 version specified.
Re: Responding to SwitchUser event in XP
i think there was a WM_ message for this.
Re: Responding to SwitchUser event in XP
if you cant use the WM_WTSSESSION_CHANGE.
other way you can consider is to listen to WM_ENDSESSION to detect logoff now at that point you can check the current logged user using the ::GetUserName(..) and start a timer or thread that start to check if the user name has changed and when it is you can stop the pausing of your app.
i now its not perfect idea but since you cant use WM_WTSSESSION_CHANGE i cant think of someting else in the moment. :)
Cheers
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by Mitsukai
i think there was a WM_ message for this.
...that's what I'm hoping for. Any ideas?
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by golanshahar
if you cant use the WM_WTSSESSION_CHANGE.
other way you can consider is to listen to
WM_ENDSESSION to detect logoff now at that point you can check the current logged user using the
::GetUserName(..) and start a timer or thread that start to check if the user name has changed and when it is you can stop the pausing of your app.
i now its not perfect idea but since you cant use WM_WTSSESSION_CHANGE i cant think of someting else in the moment. :)
Cheers
Thanks for the suggestion. I'll look into this ...
<revisited>
... actually, this won't work i don't think. Switching a user doesnt cause a WM_ENDSESSION, these apps remain running in memory so no logging off is done. If the user logs off, my app exits, so no problem anyway.
It's specifically switch user i need to cater for.
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by Igor Vartanov
Do you really think it might be other way to detect? The way to detect remains the same, but the way to compile must be different. I think it should be explicit WTSRegisterSessionNotification resolving by LoadLibrary("wtsapi32.dll")+GetProcAddress(..., "WTSRegisterSessionNotification"). :)
In case you don't find wtsapi32.dll you may be sure it's no user switching present in system.
End explicit function address resolution never could stop your compile with 0x0400 version specified.
Thanks for this idea. Like I said, it's been 2 years since I sat down in front of Visual Studio and coded, and my knowledge is rusty to the say the least. I hadn't even considered using LoadLibrary. It's a good idea, I'll try it ..
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by jase jennings
Thanks for this idea. Like I said, it's been 2 years since I sat down in front of Visual Studio and coded, and my knowledge is rusty to the say the least. I hadn't even considered using LoadLibrary. It's a good idea, I'll try it ..
Sorry Igor. I am struggling with GetProcAddress(). It's been such a long time ...
I cannot work out the rest of the code required here :
Code:
m_hInstWtsapi32 = LoadLibrary("wtsapi32.dll");
if(m_hInstWtsapi32!=NULL)
{
// switch user available (windows terminal services)
???? = GetProcAddress(m_hInstWtsapi32, "WTSRegisterSessionNotification").
}
I can't figure the data type to declare which will be returned by GetProcAddress(), and I've no idea how I will then call the function and make provision for handling the message callback this way.
I'll need some more help with the syntax, or I'm right back to looking for an alternative method.
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by jase jennings
Sorry Igor. I am struggling with GetProcAddress(). It's been such a long time ...
I cannot work out the rest of the code required here :
Code:
m_hInstWtsapi32 = LoadLibrary("wtsapi32.dll");
if(m_hInstWtsapi32!=NULL)
{
// switch user available (windows terminal services)
???? = GetProcAddress(m_hInstWtsapi32, "WTSRegisterSessionNotification").
}
I can't figure the data type to declare which will be returned by GetProcAddress(), and I've no idea how I will then call the function and make provision for handling the message callback this way.
I'll need some more help with the syntax, or I'm right back to looking for an alternative method.
lok at this code:
Code:
typedef DWORD (WINAPI *tWTSRegisterSessionNotification)( HWND,DWORD );
tWTSRegisterSessionNotification pWTSRegisterSessionNotification=0;
HINSTANCE handle = ::LoadLibrary("wtsapi32.dll");
if ( handle == 0 )
return;
pWTSRegisterSessionNotification = (tWTSRegisterSessionNotification) ::GetProcAddress(handle,"WTSRegisterSessionNotification");
if ( pWTSRegisterSessionNotification)
{
// call the fucntion
pWTSRegisterSessionNotification(/*hWnd*/,/*dwFlags*/);
}
::FreeLibrary(handle);
Cheers
Re: Responding to SwitchUser event in XP
Thanks a lot for that code, I'm please you posted it because I did manage to put something together and I'm relieved to see that your code is very similar to mine :) I shall use yours though, as my typedef was a little different and possibly wrong ...
Getting back to the problem though, I am still unable to compile without setting _WIN32_WINNT to 0x0501, as the message WM_WTSESSION_CHANGE is unavailable without it.
Code:
//from winuser.h
#if(_WIN32_WINNT >= 0x0501)
#define WM_WTSSESSION_CHANGE 0x02B1
#endif /* _WIN32_WINNT >= 0x0501 */
So, I have hard coded the message handler for 0x02B1 rather than the WM_ identifier.
It all looks ok and compiles fine, but my message handler is never called, which I expect it to do if I switch user and then switch back again.
In my dialog apps OnInitInstance, I call the function like this :
Code:
pWTSRegisterSessionNotification(GetMainWnd()->GetSafeHwnd(), NOTIFY_FOR_THIS_SESSION);
I then DoModal() on my apps main dialog. The dialog has the following message handler :
Code:
// in the .h message map
afx_msg LRESULT OnWTSessionChange(WPARAM wParam, LPARAM lParam);
// in the .cpp message map
ON_MESSAGE(0x02b1, OnWTSessionChange)//WM_WTSSESSION_CHANGE
// the actual handler
LRESULT CMyDlg::OnWTSessionChange(WPARAM wParam, LPARAM lParam)
{
AfxMessageBox("OnWTSessionChange");
return 1;
}
This handler never gets called. Can you see what I'm doing wrong?
Thanks for your continued help, much appreciated.
Re: Responding to SwitchUser event in XP
Re: Responding to SwitchUser event in XP
I don't know what GetMainWnd() is . But I just copied and pasted your code and replaced it with:
WTSRegisterSessionNotification(GetSafeHwnd(),NOTIFY_FOR_THIS_SESSION);
I see the message box, no prblem
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by kirants
I don't know what GetMainWnd() is . But I just copied and pasted your code and replaced it with:
WTSRegisterSessionNotification(GetSafeHwnd(),NOTIFY_FOR_THIS_SESSION);
I see the message box, no prblem
Well, I'm doing the LoadLibrary stuff and setting up the call back from my CWinApp derived class, so i can't use GetSafeHwnd() ...
I take it you are doing this within your CWnd derived class?
Could you tell me where you are doing the LoadLibrary() & WTSRegisterSessionNotification() calls please?
Thanks
1 Attachment(s)
Re: Responding to SwitchUser event in XP
Here is my dialog class.
As you see:
1. To keep matters simple, am not doing a loadlibrary, instead calling API directly. That shouldn't be an issue in any case, unless loadlibrary is failing for some reason on your machine.
2. I use GetSafeHwnd() in OnInitDialog. I don't know why you cannot use GetSafeHwnd(). Anyways, my first suspicion is that the HWND supplied to the WTS API is not a valid one ( possibly NULL ). So, why don't you try in 2 steps, first get HWND in whatever way you think of, and then pass it to WST API. Note that since you are handling the WM_WTSSESSION message in your dialog class, the HWND passed to the WTS registration API also has to be the HWND of your dialog object ( which again should be same as one returned by GetSafeHwnd() or by accessing the protected member m_hWnd)
Re: Responding to SwitchUser event in XP
I put the code in my dialogs InitDialog and now it all works nicely.
The documentation I had been reading suggested that the code should be place in InitInstance(), therefore in the CWinApp derived class.
The kb I was reading was specifically talking about the Windows SDK however, and not MFC.
Many thanks for trying this for me and helping me solve the problem (of my own making :)
Thanks
Re: Responding to SwitchUser event in XP
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by kirants
1. To keep matters simple, am not doing a loadlibrary, instead calling API directly. That shouldn't be an issue in any case, unless loadlibrary is failing for some reason on your machine.
The code i am writing must also run on Windows 98 and therefore i define _WIN32_WINNT as 0x0400. These wts functions require that defined to 0x0501 for xp, so my code won't compile.
That's why i need to load the wts library at runtime.
Thanks again
Re: Responding to SwitchUser event in XP
Quote:
Originally Posted by jase jennings
That's why i need to load the wts library at runtime.
Yep. Got it. I removed that only for sake of simplicity since I was testing on XP alone