7

I am currently working on some parental control software. This software is supposed to log out a user and then lock the account so that they cannot log back in unless the parent/admin has specified that they can.

I have tried several things so far such as setting flags on the user account saying that it is disabled. This completely removes it from the login screen. From what I have found out is that if the user account is logged in, it doesn't apply the ADS_Disable flag. I have also tried looking for resources on logging out another account but I can only seem to find information on logging out the account that is running the logout command. Such as Pinvoke, or directly calling the LOGOUT.EXE program.

I found a resource on LSAUser and found that there might be something there. I am doing this project for school and I am needing a little guidance. Since there is such a sparse amount of information on doing this, is there a better way of doing what I want to do? Or is there a reason why I shouldn't do this? Any alternatives?

Community
  • 1
  • 1
Rizowski
  • 3,528
  • 5
  • 22
  • 31
  • 1
    http://windows.microsoft.com/en-US/windows7/products/features/parental-controls must be an api somewhere you could tie into so you don't have to reinvent the wheel. – Marc B Jan 22 '13 at 19:24
  • I am trying to do this for Windows XP, from what I have been able to tell the Family Center doesn't support XP. – Rizowski Jan 22 '13 at 19:27
  • You may want to check out http://stackoverflow.com/questions/12112506/how-to-script-log-in-and-log-out-on-windows-xp. That's assuming you don't mind a non C# solution. Appears to be powershell based which is the de-facto way of carrying out a task of this nature. – A-Dubb Jan 22 '13 at 19:51
  • Windows has supported time-based user lockout since Windows 2000. Take a look at Group Policy, which is supported on Windows XP Home Edition. – Dai Jan 22 '13 at 20:28
  • I found this http://stackoverflow.com/questions/484278/log-off-user-from-win-xp-programmatically-in-c-sharp it might help – Mazaka Jan 22 '13 at 20:30
  • Relevant question [here](http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/c32e1117-c980-4ec4-8926-5ec6f345f903) from Microsoft. – John Alexiou Jan 22 '13 at 20:45

3 Answers3

13

Use the WTSDisconnectSession() Windows API. See article here.

using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

class Program
{
  [DllImport("wtsapi32.dll", SetLastError = true)]
  static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);

  [DllImport("Kernel32.dll", SetLastError = true)]         
  static extern int WTSGetActiveConsoleSessionId();

  const int WTS_CURRENT_SESSION = -1;
  static readonly IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;

  static void Main(string[] args)
  {
    if (!WTSDisconnectSession(WTS_CURRENT_SERVER_HANDLE,
         WTS_CURRENT_SESSION, false))
      throw new Win32Exception();
  }
}

Even without remote desktop, it will disconnect the current user and go to the login screen. The processes will still run in the background. After manually login in again, the running programs will appear as they were before the disconnect.

John Alexiou
  • 28,472
  • 11
  • 77
  • 133
  • This is awesome, do you happen to know how to get the user session id? Can I get it from the WMI? – Rizowski Jan 23 '13 at 02:48
  • 2
    You use `[DllImport("Kernel32.dll", SetLastError = true)] static extern UInt32 WTSGetActiveConsoleSessionId();` as I read it from: http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/c32e1117-c980-4ec4-8926-5ec6f345f903 – John Alexiou Jan 23 '13 at 13:30
  • Or `WTSEnumerateSessions()` from http://stackoverflow.com/questions/132620/how-do-you-retrieve-a-list-of-logged-in-connected-users-in-net – John Alexiou Jan 23 '13 at 13:31
  • @esmehsnj I don't know. Does UWP support WinAPI? Maybe not. – John Alexiou Nov 09 '20 at 22:36
  • @JohnAlexiou apparently not, according to this answer we can find the equivalent functions in WinRT https://stackoverflow.com/a/42445105/6908213 – esmehsnj Nov 10 '20 at 17:38
5
  [DllImport("wtsapi32.dll", SetLastError = true)]
  static extern bool WTSDisconnectSession(IntPtr hServer, int sessionId, bool bWait);


When you use WTSDisconnectSession in remote desktop is equivalent to 'Close' the remote desktop windows. It is disconnect your Windows session, but hold the connection.

The advantage is you can reconnect back the session later by remote log in again.
The disadvantage is the Windows may not be able log in by other user when the remote desktop connection is full.


To simulate Windows 'Log off' should use ExitWindowsEx under user32.dll

[DllImport("user32.dll", SetLastError = true)]
static extern bool ExitWindowsEx(uint uFlags, uint dwReason);

public static bool WindowsLogOff() {
  return ExitWindowsEx(0, 0);
}

if you want to Force the user to log off you need to add the EWX_FORCE flag like this:

ExitWindowsEx(0 | 0x00000004, 0);

More details on the function here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376868(v=vs.85).aspx

jgauffin
  • 99,844
  • 45
  • 235
  • 372
Leng Weh Seng
  • 725
  • 8
  • 6
  • How to Log off other user logged in? – Ibai Jan 23 '20 at 09:00
  • How to forcefully log off selected user from the Remote machine by using ExitWindowsEx . For example we have 3 remote users logged in. And we want to log off a specific user bu its session id. How we can do this by using ExitWindowsEx. – Hassan Iftikhar Feb 11 '22 at 13:51
2

piggybacking off Leng Weh Seng's answer (since I can't comment), if you want to Force the user to log off you need to add the EWX_FORCE flag like this:

ExitWindowsEx(0 | 0x00000004, 0);

More details on the function here: https://msdn.microsoft.com/en-us/library/windows/desktop/aa376868(v=vs.85).aspx

prw56
  • 326
  • 2
  • 12