Answered by:
how to force the interactive user to logoff

Question
-
is there a way for a service to force the interactive user to logoff? the ExitWindowsEx API applies to caller's desktop, so i don't think this works from a service to shut down another user. i'm trying to write a program that is similar to cybercafe software -once a user has used up their allotted time (to be monitored by the service), i want to force that user's desktop to lock or logoff. if i have a timer program running within the user's session that initiates the logoff, then the user could (in theory) cancel that process.Tuesday, February 27, 2007 1:37 AM
Answers
-
The problem is in the parameters of the WTSDisconnectSession.
WTS_CURRENT_SESSION -> Indicates the session of the process that is calling the method. In your case, session 0 (which is the services session)
The interactive (user) session starts at 1. The first logged user gets session 1, then session 2, etc ... There is a command line tool called QWinsta.exe that list all the machine's sessions.
So if in your environment only one user can log on you can do:
WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,1,false);
If more than one user can log on to the machine, first you need to determine which user you want to log off, get its session Id and use it. You can use the WTSEnumerateSessions method to list all of the machine's sessions.
Regards,
David Hernández Díez
Friday, March 9, 2007 10:38 AM
All replies
-
In Windows Vista services are run in session 0, which is non interactive. Users that log on to the system starts in session 1, 2 ...
XP was different since the services and the first logged on user run in the same session. If you are in a Fast user Switching scenario you also need to apply one of these two solution.
In Vista you have two options:
Use WTSDisconnectSession that disconnects the user (it's not a logoff). This call can be made directly in your windows service call.
Use the CreateProcessAsUser method and call an .exe that calls the ExitWindowsEx method. You need an extra executable to do what you need.
Regards,
David Hernández Díez
Tuesday, February 27, 2007 10:33 AM -
I assume the WTSDisconnectSession option only applies if Terminal Services are being used. I need a solution for a regular Home Premium or even Home Basic version of Vista, with a normal windows logon (not Remote Desktop), so I doubt this will work for my application. On the other hand, I found a post that mentions calling "WTSGetActiveConsoleSessionId" which it sounds like will work even without Terminal Services running. So I'm a little confused about whether this approach will work. Is this equivalent to the "Switch User" button? If yes, this is a good approach because the user won't lose their work and admin can go add more time for the user so they can sign in and resume work. Do you know if the user can cancel this operation? I found a .NET event - Application.SessionEnding - which makes it look like any application can cancel.
Using CreateProcessAsUser sounds like a good idea. The problem with ExitWindowsEx is the user might lose data. I found another post that describes more of the details:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=404082&SiteID=1
If I can't force a "Switch User", another approach might be to use CreateProcessAsUser to create another Desktop (SwitchDesktop), where the only thing that can be done there is to log off or give an administrator the option to add more time to the user's session (which would destroy that desktop and return the user to their normal desktop). Do you know if this approach would work? Or can the user still press Ctrl+Alt+Del, choose the TaskMgr, and destroy this alternate desktop?
Thanks for your help.
Tuesday, February 27, 2007 7:18 PM -
method starting with WTS (like WTSDisconnectSession) were originaly designed for terminal services, but since fast User Switching they can be used in XP and Vista. No terminal Services (or any remote calls) are required.
WTSDisconnectSession is lke a "Swich User", the user will be "kicked out" of the session but it wil remain active, the user cannot cancel the operation but he can log in again in that session.
You mentioned you wanted a log off. That implies that if you force a log off and the user has any widow opened it may loose data. Anyways that method has a boolean parameter (force) that tells if you want to give the option to the user to cancel that action.
The alternate desktop, doesn't block any system key like Ctrl+Alt+Del or Ctrl+Shift+Esc. Anyways It may be a good idea to hide all the user applications and show a custom dialog.
If you want to create a kiosk application you should block, somehow, that key combinations or the user may "do things" that you don't want the user to do. for example stop the application that counts the remaining time.
regards,
David Hernández Díez
Wednesday, February 28, 2007 11:57 AM -
ExitWindowsEx indeed applies to the session of the caller.
If you want a forced logoff from the service, you don't need CPAU + ExitWindowsEx.
Consider WTSLogoffSession. These WTS APIs are present on all SKUs.
Data loss (in case the user hasn't saved some files for example) is possible.But if you want the logoff to be interactive (the user will be given the choice to save unsaved work, but can also cancel the logoff), you could use CPAU on logoff.exe...
Thursday, March 1, 2007 10:44 PM -
I've gotten WTSDisconnectSession to work in a WinForms and console app using c# and pinvoke. But in a Windows Service on Vista, with logon as Local System it doesn't do anything. I'm stuck. Here is the code:
[DllImport("WtsApi32.dll", SetLastError = true)]
private static extern bool WTSDisconnectSession(IntPtr hServer, UInt32 sessionID, Int32 bWait);static void Main(string[] args)
{
UInt32 WTS_CURRENT_SESSION = UInt32.MaxValue;
IntPtr WTS_CURRENT_SERVER_HANDLE = new IntPtr();
WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, 0);
}Friday, March 9, 2007 1:09 AM -
The problem is in the parameters of the WTSDisconnectSession.
WTS_CURRENT_SESSION -> Indicates the session of the process that is calling the method. In your case, session 0 (which is the services session)
The interactive (user) session starts at 1. The first logged user gets session 1, then session 2, etc ... There is a command line tool called QWinsta.exe that list all the machine's sessions.
So if in your environment only one user can log on you can do:
WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,1,false);
If more than one user can log on to the machine, first you need to determine which user you want to log off, get its session Id and use it. You can use the WTSEnumerateSessions method to list all of the machine's sessions.
Regards,
David Hernández Díez
Friday, March 9, 2007 10:38 AM -
It also works to use...
[DllImport("Kernel32.dll", SetLastError = true)]
static extern UInt32 WTSGetActiveConsoleSessionId();... to get the session ID to disconnect.
Friday, March 9, 2007 7:22 PM -
Hello,
I've been able to Disconnect and LogOff a Session from an ASP.NET page, using machine IP and sessionId, in my development environment (Visual Studio 2005 webdev webserver).
public
static bool DisconnectSession(string ServerName, int sessionId){
IntPtr server = IntPtr.Zero;
server = OpenServer(ServerName);
bool res = WTSDisconnectSession(server, sessionId, false);
CloseServer(server);
return res;
}
public static bool LogOffSession(string ServerName, int sessionId)
{
IntPtr server = IntPtr.Zero;
server = OpenServer(ServerName);
bool res = WTSLogoffSession(server, sessionId, false);
CloseServer(server);
return res;
}
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);
[DllImport("wtsapi32.dll", SetLastError = true)]
static extern bool WTSLogoffSession(IntPtr hServer, int SessionId, bool bWait);
However, since I've installed this application in a Windows 2003 Server environment, with IIS 6, these two functions have stopped working.
I believe it is a IIS permissions problem against the machine it is trying to connect to, but have not found any clue yet.
Any help would be very appreciated. This is kind of urgent for my company.
Thanks in advance.Wednesday, March 4, 2009 2:03 PM